This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.git] / binutils / resrc.c
1 /* resrc.c -- read and write Windows rc files.
2    Copyright 1997, 1998 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 file contains functions that read and write Windows rc files.
23    These are text files that represent resources.  */
24
25 #include "bfd.h"
26 #include "bucomm.h"
27 #include "libiberty.h"
28 #include "windres.h"
29
30 #include <assert.h>
31 #include <ctype.h>
32 #include <sys/stat.h>
33
34 #if defined (_WIN32) && ! defined (__CYGWIN32__)
35 #define popen _popen
36 #define pclose _pclose
37 #endif
38
39 /* The default preprocessor.  */
40
41 #define DEFAULT_PREPROCESSOR "gcc -E -xc-header -DRC_INVOKED"
42
43 /* We read the directory entries in a cursor or icon file into
44    instances of this structure.  */
45
46 struct icondir
47 {
48   /* Width of image.  */
49   unsigned char width;
50   /* Height of image.  */
51   unsigned char height;
52   /* Number of colors in image.  */
53   unsigned char colorcount;
54   union
55   {
56     struct
57     {
58       /* Color planes.  */
59       unsigned short planes;
60       /* Bits per pixel.  */
61       unsigned short bits;
62     } icon;
63     struct
64     {
65       /* X coordinate of hotspot.  */
66       unsigned short xhotspot;
67       /* Y coordinate of hotspot.  */
68       unsigned short yhotspot;
69     } cursor;
70   } u;
71   /* Bytes in image.  */
72   unsigned long bytes;
73   /* File offset of image.  */
74   unsigned long offset;
75 };
76
77 /* The name of the rc file we are reading.  */
78
79 char *rc_filename;
80
81 /* The line number in the rc file.  */
82
83 int rc_lineno;
84
85 /* The pipe we are reading from, so that we can close it if we exit.  */
86
87 static FILE *cpp_pipe;
88
89 /* As we read the rc file, we attach information to this structure.  */
90
91 static struct res_directory *resources;
92
93 /* The number of cursor resources we have written out.  */
94
95 static int cursors;
96
97 /* The number of font resources we have written out.  */
98
99 static int fonts;
100
101 /* Font directory information.  */
102
103 struct fontdir *fontdirs;
104
105 /* Resource info to use for fontdirs.  */
106
107 struct res_res_info fontdirs_resinfo;
108
109 /* The number of icon resources we have written out.  */
110
111 static int icons;
112
113 /* Local functions.  */
114
115 static void close_pipe PARAMS ((void));
116 static void unexpected_eof PARAMS ((const char *));
117 static int get_word PARAMS ((FILE *, const char *));
118 static unsigned long get_long PARAMS ((FILE *, const char *));
119 static void get_data
120   PARAMS ((FILE *, unsigned char *, unsigned long, const char *));
121 static void define_fontdirs PARAMS ((void));
122 \f
123 /* Read an rc file.  */
124
125 struct res_directory *
126 read_rc_file (filename, preprocessor, preprocargs, language)
127      const char *filename;
128      const char *preprocessor;
129      const char *preprocargs;
130      int language;
131 {
132   char *cmd;
133
134   if (preprocessor == NULL)
135     preprocessor = DEFAULT_PREPROCESSOR;
136
137   if (preprocargs == NULL)
138     preprocargs = "";
139   if (filename == NULL)
140     filename = "-";
141
142   cmd = xmalloc (strlen (preprocessor)
143                  + strlen (preprocargs)
144                  + strlen (filename)
145                  + 10);
146   sprintf (cmd, "%s %s %s", preprocessor, preprocargs, filename);
147
148   cpp_pipe = popen (cmd, FOPEN_RT);
149   if (cpp_pipe == NULL)
150     fatal (_("can't popen `%s': %s"), cmd, strerror (errno));
151   free (cmd);
152
153   xatexit (close_pipe);
154
155   rc_filename = xstrdup (filename);
156   rc_lineno = 1;
157   if (language != -1)
158     rcparse_set_language (language);
159   yyin = cpp_pipe;
160   yyparse ();
161
162   if (pclose (cpp_pipe) != 0)
163     fprintf (stderr, _("%s: warning: preprocessor failed\n"), program_name);
164   cpp_pipe = NULL;
165
166   if (fontdirs != NULL)
167     define_fontdirs ();
168
169   free (rc_filename);
170   rc_filename = NULL;
171
172   return resources;
173 }
174
175 /* Close the pipe if it is open.  This is called via xatexit.  */
176
177 void
178 close_pipe ()
179 {
180   if (cpp_pipe != NULL)
181     pclose (cpp_pipe);
182 }
183
184 /* Report an error while reading an rc file.  */
185
186 void
187 yyerror (msg)
188      const char *msg;
189 {
190   fatal ("%s:%d: %s", rc_filename, rc_lineno, msg);
191 }
192
193 /* Issue a warning while reading an rc file.  */
194
195 void
196 rcparse_warning (msg)
197      const char *msg;
198 {
199   fprintf (stderr, "%s:%d: %s\n", rc_filename, rc_lineno, msg);
200 }
201
202 /* Die if we get an unexpected end of file.  */
203
204 static void
205 unexpected_eof (msg)
206      const char *msg;
207 {
208   fatal (_("%s: unexpected EOF"), msg);
209 }
210
211 /* Read a 16 bit word from a file.  The data is assumed to be little
212    endian.  */
213
214 static int
215 get_word (e, msg)
216      FILE *e;
217      const char *msg;
218 {
219   int b1, b2;
220
221   b1 = getc (e);
222   b2 = getc (e);
223   if (feof (e))
224     unexpected_eof (msg);
225   return ((b2 & 0xff) << 8) | (b1 & 0xff);
226 }
227
228 /* Read a 32 bit word from a file.  The data is assumed to be little
229    endian.  */
230
231 static unsigned long
232 get_long (e, msg)
233      FILE *e;
234      const char *msg;
235 {
236   int b1, b2, b3, b4;
237
238   b1 = getc (e);
239   b2 = getc (e);
240   b3 = getc (e);
241   b4 = getc (e);
242   if (feof (e))
243     unexpected_eof (msg);
244   return (((((((b4 & 0xff) << 8)
245               | (b3 & 0xff)) << 8)
246             | (b2 & 0xff)) << 8)
247           | (b1 & 0xff));
248 }
249
250 /* Read data from a file.  This is a wrapper to do error checking.  */
251
252 static void
253 get_data (e, p, c, msg)
254      FILE *e;
255      unsigned char *p;
256      unsigned long c;
257      const char *msg;
258 {
259   unsigned long got;
260
261   got = fread (p, 1, c, e);
262   if (got == c)
263     return;
264
265   fatal (_("%s: read of %lu returned %lu"), msg, c, got);
266 }
267 \f
268 /* Define an accelerator resource.  */
269
270 void
271 define_accelerator (id, resinfo, data)
272      struct res_id id;
273      const struct res_res_info *resinfo;
274      struct accelerator *data;
275 {
276   struct res_resource *r;
277
278   r = define_standard_resource (&resources, RT_ACCELERATOR, id,
279                                 resinfo->language, 0);
280   r->type = RES_TYPE_ACCELERATOR;
281   r->u.acc = data;
282   r->res_info = *resinfo;
283 }
284
285 /* Define a bitmap resource.  Bitmap data is stored in a file.  The
286    first 14 bytes of the file are a standard header, which is not
287    included in the resource data.  */
288
289 #define BITMAP_SKIP (14)
290
291 void
292 define_bitmap (id, resinfo, filename)
293      struct res_id id;
294      const struct res_res_info *resinfo;
295      const char *filename;
296 {
297   FILE *e;
298   char *real_filename;
299   struct stat s;
300   unsigned char *data;
301   int i;
302   struct res_resource *r;
303
304   e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename);
305
306   if (stat (real_filename, &s) < 0)
307     fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
308            strerror (errno));
309
310   data = (unsigned char *) res_alloc (s.st_size - BITMAP_SKIP);
311
312   for (i = 0; i < BITMAP_SKIP; i++)
313     getc (e);
314
315   get_data (e, data, s.st_size - BITMAP_SKIP, real_filename);
316
317   fclose (e);
318   free (real_filename);
319
320   r = define_standard_resource (&resources, RT_BITMAP, id,
321                                 resinfo->language, 0);
322
323   r->type = RES_TYPE_BITMAP;
324   r->u.data.length = s.st_size - BITMAP_SKIP;
325   r->u.data.data = data;
326   r->res_info = *resinfo;
327 }
328
329 /* Define a cursor resource.  A cursor file may contain a set of
330    bitmaps, each representing the same cursor at various different
331    resolutions.  They each get written out with a different ID.  The
332    real cursor resource is then a group resource which can be used to
333    select one of the actual cursors.  */
334
335 void
336 define_cursor (id, resinfo, filename)
337      struct res_id id;
338      const struct res_res_info *resinfo;
339      const char *filename;
340 {
341   FILE *e;
342   char *real_filename;
343   int type, count, i;
344   struct icondir *icondirs;
345   int first_cursor;
346   struct res_resource *r;
347   struct group_cursor *first, **pp;
348
349   e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename);
350
351   /* A cursor file is basically an icon file.  The start of the file
352      is a three word structure.  The first word is ignored.  The
353      second word is the type of data.  The third word is the number of
354      entries.  */
355
356   get_word (e, real_filename);
357   type = get_word (e, real_filename);
358   count = get_word (e, real_filename);
359   if (type != 2)
360     fatal (_("cursor file `%s' does not contain cursor data"), real_filename);
361
362   /* Read in the icon directory entries.  */
363
364   icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
365
366   for (i = 0; i < count; i++)
367     {
368       icondirs[i].width = getc (e);
369       icondirs[i].height = getc (e);
370       icondirs[i].colorcount = getc (e);
371       getc (e);
372       icondirs[i].u.cursor.xhotspot = get_word (e, real_filename);
373       icondirs[i].u.cursor.yhotspot = get_word (e, real_filename);
374       icondirs[i].bytes = get_long (e, real_filename);
375       icondirs[i].offset = get_long (e, real_filename);
376
377       if (feof (e))
378         unexpected_eof (real_filename);
379     }
380
381   /* Define each cursor as a unique resource.  */
382
383   first_cursor = cursors;
384
385   for (i = 0; i < count; i++)
386     {
387       unsigned char *data;
388       struct res_id name;
389       struct cursor *c;
390
391       if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
392         fatal (_("%s: fseek to %lu failed: %s"), real_filename,
393                icondirs[i].offset, strerror (errno));
394
395       data = (unsigned char *) res_alloc (icondirs[i].bytes);
396
397       get_data (e, data, icondirs[i].bytes, real_filename);
398
399       c = (struct cursor *) res_alloc (sizeof *c);
400       c->xhotspot = icondirs[i].u.cursor.xhotspot;
401       c->yhotspot = icondirs[i].u.cursor.yhotspot;
402       c->length = icondirs[i].bytes;
403       c->data = data;
404
405       ++cursors;
406
407       name.named = 0;
408       name.u.id = cursors;
409
410       r = define_standard_resource (&resources, RT_CURSOR, name,
411                                     resinfo->language, 0);
412       r->type = RES_TYPE_CURSOR;
413       r->u.cursor = c;
414       r->res_info = *resinfo;
415     }
416
417   fclose (e);
418   free (real_filename);
419
420   /* Define a cursor group resource.  */
421
422   first = NULL;
423   pp = &first;
424   for (i = 0; i < count; i++)
425     {
426       struct group_cursor *cg;
427
428       cg = (struct group_cursor *) res_alloc (sizeof *cg);
429       cg->next = NULL;
430       cg->width = icondirs[i].width;
431       cg->height = 2 * icondirs[i].height;
432
433       /* FIXME: What should these be set to?  */
434       cg->planes = 1;
435       cg->bits = 1;
436
437       cg->bytes = icondirs[i].bytes + 4;
438       cg->index = first_cursor + i + 1;
439
440       *pp = cg;
441       pp = &(*pp)->next;
442     }
443
444   free (icondirs);
445
446   r = define_standard_resource (&resources, RT_GROUP_CURSOR, id,
447                                 resinfo->language, 0);
448   r->type = RES_TYPE_GROUP_CURSOR;
449   r->u.group_cursor = first;
450   r->res_info = *resinfo;
451 }
452
453 /* Define a dialog resource.  */
454
455 void
456 define_dialog (id, resinfo, dialog)
457      struct res_id id;
458      const struct res_res_info *resinfo;
459      const struct dialog *dialog;
460 {
461   struct dialog *copy;
462   struct res_resource *r;
463
464   copy = (struct dialog *) res_alloc (sizeof *copy);
465   *copy = *dialog;
466
467   r = define_standard_resource (&resources, RT_DIALOG, id,
468                                 resinfo->language, 0);
469   r->type = RES_TYPE_DIALOG;
470   r->u.dialog = copy;
471   r->res_info = *resinfo;
472 }
473
474 /* Define a dialog control.  This does not define a resource, but
475    merely allocates and fills in a structure.  */
476
477 struct dialog_control *
478 define_control (text, id, x, y, width, height, class, style, exstyle)
479      const char *text;
480      unsigned long id;
481      unsigned long x;
482      unsigned long y;
483      unsigned long width;
484      unsigned long height;
485      unsigned long class;
486      unsigned long style;
487      unsigned long exstyle;
488 {
489   struct dialog_control *n;
490
491   n = (struct dialog_control *) res_alloc (sizeof *n);
492   n->next = NULL;
493   n->id = id;
494   n->style = style;
495   n->exstyle = exstyle;
496   n->x = x;
497   n->y = y;
498   n->width = width;
499   n->height = height;
500   n->class.named = 0;
501   n->class.u.id = class;
502   if (text != NULL)
503     res_string_to_id (&n->text, text);
504   else
505     {
506       n->text.named = 0;
507       n->text.u.id = 0;
508     }
509   n->data = NULL;
510   n->help = 0;
511
512   return n;
513 }
514
515 /* Define a font resource.  */
516
517 void
518 define_font (id, resinfo, filename)
519      struct res_id id;
520      const struct res_res_info *resinfo;
521      const char *filename;
522 {
523   FILE *e;
524   char *real_filename;
525   struct stat s;
526   unsigned char *data;
527   struct res_resource *r;
528   long offset;
529   long fontdatalength;
530   unsigned char *fontdata;
531   struct fontdir *fd;
532   const char *device, *face;
533   struct fontdir **pp;
534
535   e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
536
537   if (stat (real_filename, &s) < 0)
538     fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
539            strerror (errno));
540
541   data = (unsigned char *) res_alloc (s.st_size);
542
543   get_data (e, data, s.st_size, real_filename);
544
545   fclose (e);
546   free (real_filename);
547
548   r = define_standard_resource (&resources, RT_FONT, id,
549                                 resinfo->language, 0);
550
551   r->type = RES_TYPE_FONT;
552   r->u.data.length = s.st_size;
553   r->u.data.data = data;
554   r->res_info = *resinfo;
555
556   /* For each font resource, we must add an entry in the FONTDIR
557      resource.  The FONTDIR resource includes some strings in the font
558      file.  To find them, we have to do some magic on the data we have
559      read.  */
560
561   offset = ((((((data[47] << 8)
562                 | data[46]) << 8)
563               | data[45]) << 8)
564             | data[44]);
565   if (offset > 0 && offset < s.st_size)
566     device = (char *) data + offset;
567   else
568     device = "";
569
570   offset = ((((((data[51] << 8)
571                 | data[50]) << 8)
572               | data[49]) << 8)
573             | data[48]);
574   if (offset > 0 && offset < s.st_size)
575     face = (char *) data + offset;
576   else
577     face = "";
578
579   ++fonts;
580
581   fontdatalength = 58 + strlen (device) + strlen (face);
582   fontdata = (unsigned char *) res_alloc (fontdatalength);
583   memcpy (fontdata, data, 56);
584   strcpy ((char *) fontdata + 56, device);
585   strcpy ((char *) fontdata + 57 + strlen (device), face);
586
587   fd = (struct fontdir *) res_alloc (sizeof *fd);
588   fd->next = NULL;
589   fd->index = fonts;
590   fd->length = fontdatalength;
591   fd->data = fontdata;
592
593   for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next)
594     ;
595   *pp = fd;
596
597   /* For the single fontdirs resource, we always use the resource
598      information of the last font.  I don't know what else to do.  */
599   fontdirs_resinfo = *resinfo;
600 }
601
602 /* Define the fontdirs resource.  This is called after the entire rc
603    file has been parsed, if any font resources were seen.  */
604
605 static void
606 define_fontdirs ()
607 {
608   struct res_resource *r;
609   struct res_id id;
610
611   id.named = 0;
612   id.u.id = 1;
613
614   r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
615
616   r->type = RES_TYPE_FONTDIR;
617   r->u.fontdir = fontdirs;
618   r->res_info = fontdirs_resinfo;
619 }
620
621 /* Define an icon resource.  An icon file may contain a set of
622    bitmaps, each representing the same icon at various different
623    resolutions.  They each get written out with a different ID.  The
624    real icon resource is then a group resource which can be used to
625    select one of the actual icon bitmaps.  */
626
627 void
628 define_icon (id, resinfo, filename)
629      struct res_id id;
630      const struct res_res_info *resinfo;
631      const char *filename;
632 {
633   FILE *e;
634   char *real_filename;
635   int type, count, i;
636   struct icondir *icondirs;
637   int first_icon;
638   struct res_resource *r;
639   struct group_icon *first, **pp;
640
641   e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename);
642
643   /* The start of an icon file is a three word structure.  The first
644      word is ignored.  The second word is the type of data.  The third
645      word is the number of entries.  */
646
647   get_word (e, real_filename);
648   type = get_word (e, real_filename);
649   count = get_word (e, real_filename);
650   if (type != 1)
651     fatal (_("icon file `%s' does not contain icon data"), real_filename);
652
653   /* Read in the icon directory entries.  */
654
655   icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
656
657   for (i = 0; i < count; i++)
658     {
659       icondirs[i].width = getc (e);
660       icondirs[i].height = getc (e);
661       icondirs[i].colorcount = getc (e);
662       getc (e);
663       icondirs[i].u.icon.planes = get_word (e, real_filename);
664       icondirs[i].u.icon.bits = get_word (e, real_filename);
665       icondirs[i].bytes = get_long (e, real_filename);
666       icondirs[i].offset = get_long (e, real_filename);
667
668       if (feof (e))
669         unexpected_eof (real_filename);
670     }
671
672   /* Define each icon as a unique resource.  */
673
674   first_icon = icons;
675
676   for (i = 0; i < count; i++)
677     {
678       unsigned char *data;
679       struct res_id name;
680
681       if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
682         fatal (_("%s: fseek to %lu failed: %s"), real_filename,
683                icondirs[i].offset, strerror (errno));
684
685       data = (unsigned char *) res_alloc (icondirs[i].bytes);
686
687       get_data (e, data, icondirs[i].bytes, real_filename);
688
689       ++icons;
690
691       name.named = 0;
692       name.u.id = icons;
693
694       r = define_standard_resource (&resources, RT_ICON, name,
695                                     resinfo->language, 0);
696       r->type = RES_TYPE_ICON;
697       r->u.data.length = icondirs[i].bytes;
698       r->u.data.data = data;
699       r->res_info = *resinfo;
700     }
701
702   fclose (e);
703   free (real_filename);
704
705   /* Define an icon group resource.  */
706
707   first = NULL;
708   pp = &first;
709   for (i = 0; i < count; i++)
710     {
711       struct group_icon *cg;
712
713       /* For some reason, at least in some files the planes and bits
714          are zero.  We instead set them from the color.  This is
715          copied from rcl.  */
716
717       cg = (struct group_icon *) res_alloc (sizeof *cg);
718       cg->next = NULL;
719       cg->width = icondirs[i].width;
720       cg->height = icondirs[i].height;
721       cg->colors = icondirs[i].colorcount;
722
723       cg->planes = 1;
724       cg->bits = 0;
725       while ((1 << cg->bits) < cg->colors)
726         ++cg->bits;
727
728       cg->bytes = icondirs[i].bytes;
729       cg->index = first_icon + i + 1;
730
731       *pp = cg;
732       pp = &(*pp)->next;
733     }
734
735   free (icondirs);
736
737   r = define_standard_resource (&resources, RT_GROUP_ICON, id,
738                                 resinfo->language, 0);
739   r->type = RES_TYPE_GROUP_ICON;
740   r->u.group_icon = first;
741   r->res_info = *resinfo;
742 }
743
744 /* Define a menu resource.  */
745
746 void
747 define_menu (id, resinfo, menuitems)
748      struct res_id id;
749      const struct res_res_info *resinfo;
750      struct menuitem *menuitems;
751 {
752   struct menu *m;
753   struct res_resource *r;
754
755   m = (struct menu *) res_alloc (sizeof *m);
756   m->items = menuitems;
757   m->help = 0;
758
759   r = define_standard_resource (&resources, RT_MENU, id, resinfo->language, 0);
760   r->type = RES_TYPE_MENU;
761   r->u.menu = m;
762   r->res_info = *resinfo;
763 }
764
765 /* Define a menu item.  This does not define a resource, but merely
766    allocates and fills in a structure.  */
767
768 struct menuitem *
769 define_menuitem (text, menuid, type, state, help, menuitems)
770      const char *text;
771      int menuid;
772      unsigned long type;
773      unsigned long state;
774      unsigned long help;
775      struct menuitem *menuitems;
776 {
777   struct menuitem *mi;
778
779   mi = (struct menuitem *) res_alloc (sizeof *mi);
780   mi->next = NULL;
781   mi->type = type;
782   mi->state = state;
783   mi->id = menuid;
784   if (text == NULL)
785     mi->text = NULL;
786   else
787     unicode_from_ascii ((int *) NULL, &mi->text, text);
788   mi->help = help;
789   mi->popup = menuitems;
790   return mi;
791 }
792
793 /* Define a messagetable resource.  */
794
795 void
796 define_messagetable (id, resinfo, filename)
797      struct res_id id;
798      const struct res_res_info *resinfo;
799      const char *filename;
800 {
801   FILE *e;
802   char *real_filename;
803   struct stat s;
804   unsigned char *data;
805   struct res_resource *r;
806
807   e = open_file_search (filename, FOPEN_RB, "messagetable file",
808                         &real_filename);
809
810   if (stat (real_filename, &s) < 0)
811     fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
812            strerror (errno));
813
814   data = (unsigned char *) res_alloc (s.st_size);
815
816   get_data (e, data, s.st_size, real_filename);
817
818   fclose (e);
819   free (real_filename);
820
821   r = define_standard_resource (&resources, RT_MESSAGETABLE, id,
822                                 resinfo->language, 0);
823
824   r->type = RES_TYPE_MESSAGETABLE;
825   r->u.data.length = s.st_size;
826   r->u.data.data = data;
827   r->res_info = *resinfo;
828 }
829
830 /* Define an rcdata resource.  */
831
832 void
833 define_rcdata (id, resinfo, data)
834      struct res_id id;
835      const struct res_res_info *resinfo;
836      struct rcdata_item *data;
837 {
838   struct res_resource *r;
839
840   r = define_standard_resource (&resources, RT_RCDATA, id,
841                                 resinfo->language, 0);
842   r->type = RES_TYPE_RCDATA;
843   r->u.rcdata = data;
844   r->res_info = *resinfo;
845 }
846
847 /* Create an rcdata item holding a string.  */
848
849 struct rcdata_item *
850 define_rcdata_string (string, len)
851      const char *string;
852      unsigned long len;
853 {
854   struct rcdata_item *ri;
855   char *s;
856
857   ri = (struct rcdata_item *) res_alloc (sizeof *ri);
858   ri->next = NULL;
859   ri->type = RCDATA_STRING;
860   ri->u.string.length = len;
861   s = (char *) res_alloc (len);
862   memcpy (s, string, len);
863   ri->u.string.s = s;
864
865   return ri;
866 }
867
868 /* Create an rcdata item holding a number.  */
869
870 struct rcdata_item *
871 define_rcdata_number (val, dword)
872      unsigned long val;
873      int dword;
874 {
875   struct rcdata_item *ri;
876
877   ri = (struct rcdata_item *) res_alloc (sizeof *ri);
878   ri->next = NULL;
879   ri->type = dword ? RCDATA_DWORD : RCDATA_WORD;
880   ri->u.word = val;
881
882   return ri;
883 }
884
885 /* Define a stringtable resource.  This is called for each string
886    which appears in a STRINGTABLE statement.  */
887
888 void
889 define_stringtable (resinfo, stringid, string)
890      const struct res_res_info *resinfo;
891      unsigned long stringid;
892      const char *string;
893 {
894   struct res_id id;
895   struct res_resource *r;
896
897   id.named = 0;
898   id.u.id = (stringid >> 4) + 1;
899   r = define_standard_resource (&resources, RT_STRING, id,
900                                 resinfo->language, 1);
901
902   if (r->type == RES_TYPE_UNINITIALIZED)
903     {
904       int i;
905
906       r->type = RES_TYPE_STRINGTABLE;
907       r->u.stringtable = ((struct stringtable *)
908                           res_alloc (sizeof (struct stringtable)));
909       for (i = 0; i < 16; i++)
910         {
911           r->u.stringtable->strings[i].length = 0;
912           r->u.stringtable->strings[i].string = NULL;
913         }
914
915       r->res_info = *resinfo;
916     }
917
918   unicode_from_ascii (&r->u.stringtable->strings[stringid & 0xf].length,
919                       &r->u.stringtable->strings[stringid & 0xf].string,
920                       string);
921 }
922
923 /* Define a user data resource where the data is in the rc file.  */
924
925 void
926 define_user_data (id, type, resinfo, data)
927      struct res_id id;
928      struct res_id type;
929      const struct res_res_info *resinfo;
930      struct rcdata_item *data;
931 {
932   struct res_id ids[3];
933   struct res_resource *r;
934
935   ids[0] = type;
936   ids[1] = id;
937   ids[2].named = 0;
938   ids[2].u.id = resinfo->language;
939
940   r = define_resource (&resources, 3, ids, 0);
941   r->type = RES_TYPE_USERDATA;
942   r->u.userdata = data;
943   r->res_info = *resinfo;
944 }
945
946 /* Define a user data resource where the data is in a file.  */
947
948 void
949 define_user_file (id, type, resinfo, filename)
950      struct res_id id;
951      struct res_id type;
952      const struct res_res_info *resinfo;
953      const char *filename;
954 {
955   FILE *e;
956   char *real_filename;
957   struct stat s;
958   unsigned char *data;
959   struct res_id ids[3];
960   struct res_resource *r;
961
962   e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
963
964   if (stat (real_filename, &s) < 0)
965     fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
966            strerror (errno));
967
968   data = (unsigned char *) res_alloc (s.st_size);
969
970   get_data (e, data, s.st_size, real_filename);
971
972   fclose (e);
973   free (real_filename);
974
975   ids[0] = type;
976   ids[1] = id;
977   ids[2].named = 0;
978   ids[2].u.id = resinfo->language;
979
980   r = define_resource (&resources, 3, ids, 0);
981   r->type = RES_TYPE_USERDATA;
982   r->u.userdata = ((struct rcdata_item *)
983                    res_alloc (sizeof (struct rcdata_item)));
984   r->u.userdata->next = NULL;
985   r->u.userdata->type = RCDATA_BUFFER;
986   r->u.userdata->u.buffer.length = s.st_size;
987   r->u.userdata->u.buffer.data = data;
988   r->res_info = *resinfo;
989 }
990
991 /* Define a versioninfo resource.  */
992
993 void
994 define_versioninfo (id, language, fixedverinfo, verinfo)
995      struct res_id id;
996      int language;
997      struct fixed_versioninfo *fixedverinfo;
998      struct ver_info *verinfo;
999 {
1000   struct res_resource *r;
1001
1002   r = define_standard_resource (&resources, RT_VERSION, id, language, 0);
1003   r->type = RES_TYPE_VERSIONINFO;
1004   r->u.versioninfo = ((struct versioninfo *)
1005                       res_alloc (sizeof (struct versioninfo)));
1006   r->u.versioninfo->fixed = fixedverinfo;
1007   r->u.versioninfo->var = verinfo;
1008   r->res_info.language = language;
1009 }
1010
1011 /* Add string version info to a list of version information.  */
1012
1013 struct ver_info *
1014 append_ver_stringfileinfo (verinfo, language, strings)
1015      struct ver_info *verinfo;
1016      const char *language;
1017      struct ver_stringinfo *strings;
1018 {
1019   struct ver_info *vi, **pp;
1020
1021   vi = (struct ver_info *) res_alloc (sizeof *vi);
1022   vi->next = NULL;
1023   vi->type = VERINFO_STRING;
1024   unicode_from_ascii ((int *) NULL, &vi->u.string.language, language);
1025   vi->u.string.strings = strings;
1026
1027   for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1028     ;
1029   *pp = vi;
1030
1031   return verinfo;
1032 }
1033
1034 /* Add variable version info to a list of version information.  */
1035
1036 struct ver_info *
1037 append_ver_varfileinfo (verinfo, key, var)
1038      struct ver_info *verinfo;
1039      const char *key;
1040      struct ver_varinfo *var;
1041 {
1042   struct ver_info *vi, **pp;
1043
1044   vi = (struct ver_info *) res_alloc (sizeof *vi);
1045   vi->next = NULL;
1046   vi->type = VERINFO_VAR;
1047   unicode_from_ascii ((int *) NULL, &vi->u.var.key, key);
1048   vi->u.var.var = var;
1049
1050   for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1051     ;
1052   *pp = vi;
1053
1054   return verinfo;
1055 }
1056
1057 /* Append version string information to a list.  */
1058
1059 struct ver_stringinfo *
1060 append_verval (strings, key, value)
1061      struct ver_stringinfo *strings;
1062      const char *key;
1063      const char *value;
1064 {
1065   struct ver_stringinfo *vs, **pp;
1066
1067   vs = (struct ver_stringinfo *) res_alloc (sizeof *vs);
1068   vs->next = NULL;
1069   unicode_from_ascii ((int *) NULL, &vs->key, key);
1070   unicode_from_ascii ((int *) NULL, &vs->value, value);
1071
1072   for (pp = &strings; *pp != NULL; pp = &(*pp)->next)
1073     ;
1074   *pp = vs;
1075
1076   return strings;
1077 }
1078
1079 /* Append version variable information to a list.  */
1080
1081 struct ver_varinfo *
1082 append_vertrans (var, language, charset)
1083      struct ver_varinfo *var;
1084      unsigned long language;
1085      unsigned long charset;
1086 {
1087   struct ver_varinfo *vv, **pp;
1088
1089   vv = (struct ver_varinfo *) res_alloc (sizeof *vv);
1090   vv->next = NULL;
1091   vv->language = language;
1092   vv->charset = charset;
1093
1094   for (pp = &var; *pp != NULL; pp = &(*pp)->next)
1095     ;
1096   *pp = vv;
1097
1098   return var;
1099 }
1100 \f
1101 /* Local functions used to write out an rc file.  */
1102
1103 static void indent PARAMS ((FILE *, int));
1104 static void write_rc_directory
1105   PARAMS ((FILE *, const struct res_directory *, const struct res_id *,
1106            const struct res_id *, int *, int));
1107 static void write_rc_subdir
1108   PARAMS ((FILE *, const struct res_entry *, const struct res_id *,
1109            const struct res_id *, int *, int));
1110 static void write_rc_resource
1111   PARAMS ((FILE *, const struct res_id *, const struct res_id *,
1112            const struct res_resource *, int *));
1113 static void write_rc_accelerators
1114   PARAMS ((FILE *, const struct accelerator *));
1115 static void write_rc_cursor PARAMS ((FILE *, const struct cursor *));
1116 static void write_rc_group_cursor
1117   PARAMS ((FILE *, const struct group_cursor *));
1118 static void write_rc_dialog PARAMS ((FILE *, const struct dialog *));
1119 static void write_rc_dialog_control
1120   PARAMS ((FILE *, const struct dialog_control *));
1121 static void write_rc_fontdir PARAMS ((FILE *, const struct fontdir *));
1122 static void write_rc_group_icon PARAMS ((FILE *, const struct group_icon *));
1123 static void write_rc_menu PARAMS ((FILE *, const struct menu *, int));
1124 static void write_rc_menuitems
1125   PARAMS ((FILE *, const struct menuitem *, int, int));
1126 static void write_rc_rcdata PARAMS ((FILE *, const struct rcdata_item *, int));
1127 static void write_rc_stringtable
1128   PARAMS ((FILE *, const struct res_id *, const struct stringtable *));
1129 static void write_rc_versioninfo PARAMS ((FILE *, const struct versioninfo *));
1130 static void write_rc_filedata
1131   PARAMS ((FILE *, unsigned long, const unsigned char *));
1132
1133 /* Indent a given number of spaces.  */
1134
1135 static void
1136 indent (e, c)
1137      FILE *e;
1138      int c;
1139 {
1140   int i;
1141
1142   for (i = 0; i < c; i++)
1143     putc (' ', e);
1144 }
1145
1146 /* Dump the resources we have read in the format of an rc file.
1147
1148    Actually, we don't use the format of an rc file, because it's way
1149    too much of a pain--for example, we'd have to write icon resources
1150    into a file and refer to that file.  We just generate a readable
1151    format that kind of looks like an rc file, and is useful for
1152    understanding the contents of a resource file.  Someday we may want
1153    to generate an rc file which the rc compiler can read; if that day
1154    comes, this code will have to be fixed up.  */
1155
1156 void
1157 write_rc_file (filename, resources)
1158      const char *filename;
1159      const struct res_directory *resources;
1160 {
1161   FILE *e;
1162   int language;
1163
1164   if (filename == NULL)
1165     e = stdout;
1166   else
1167     {
1168       e = fopen (filename, FOPEN_WT);
1169       if (e == NULL)
1170         fatal (_("can't open `%s' for output: %s"), filename, strerror (errno));
1171     }
1172
1173   language = -1;
1174   write_rc_directory (e, resources, (const struct res_id *) NULL,
1175                       (const struct res_id *) NULL, &language, 1);
1176 }
1177
1178 /* Write out a directory.  E is the file to write to.  RD is the
1179    directory.  TYPE is a pointer to the level 1 ID which serves as the
1180    resource type.  NAME is a pointer to the level 2 ID which serves as
1181    an individual resource name.  LANGUAGE is a pointer to the current
1182    language.  LEVEL is the level in the tree.  */
1183
1184 static void
1185 write_rc_directory (e, rd, type, name, language, level)
1186      FILE *e;
1187      const struct res_directory *rd;
1188      const struct res_id *type;
1189      const struct res_id *name;
1190      int *language;
1191      int level;
1192 {
1193   const struct res_entry *re;
1194
1195   /* Print out some COFF information that rc files can't represent.  */
1196
1197   if (rd->time != 0)
1198     fprintf (e, "// Time stamp: %lu\n", rd->time);
1199   if (rd->characteristics != 0)
1200     fprintf (e, "// Characteristics: %lu\n", rd->characteristics);
1201   if (rd->major != 0 || rd->minor != 0)
1202     fprintf (e, "// Version: %d %d\n", rd->major, rd->minor);
1203
1204   for (re = rd->entries;  re != NULL; re = re->next)
1205     {
1206       switch (level)
1207         {
1208         case 1:
1209           /* If we're at level 1, the key of this resource is the
1210              type.  This normally duplicates the information we have
1211              stored with the resource itself, but we need to remember
1212              the type if this is a user define resource type.  */
1213           type = &re->id;
1214           break;
1215
1216         case 2:
1217           /* If we're at level 2, the key of this resource is the name
1218              we are going to use in the rc printout. */
1219           name = &re->id;
1220           break;
1221
1222         case 3:
1223           /* If we're at level 3, then this key represents a language.
1224              Use it to update the current language.  */
1225           if (! re->id.named
1226               && re->id.u.id != (unsigned long) (unsigned int) *language
1227               && (re->id.u.id & 0xffff) == re->id.u.id)
1228             {
1229               fprintf (e, "LANGUAGE %lu, %lu\n",
1230                        re->id.u.id & 0xff, (re->id.u.id >> 8) & 0xff);
1231               *language = re->id.u.id;
1232             }
1233           break;
1234
1235         default:
1236           break;
1237         }
1238
1239       if (re->subdir)
1240         write_rc_subdir (e, re, type, name, language, level);
1241       else
1242         {
1243           if (level == 3)
1244             {
1245               /* This is the normal case: the three levels are
1246                  TYPE/NAME/LANGUAGE.  NAME will have been set at level
1247                  2, and represents the name to use.  We probably just
1248                  set LANGUAGE, and it will probably match what the
1249                  resource itself records if anything.  */
1250               write_rc_resource (e, type, name, re->u.res, language);
1251             }
1252           else
1253             {
1254               fprintf (e, "// Resource at unexpected level %d\n", level);
1255               write_rc_resource (e, type, (struct res_id *) NULL, re->u.res,
1256                                  language);
1257             }
1258         }
1259     }
1260 }
1261
1262 /* Write out a subdirectory entry.  E is the file to write to.  RE is
1263    the subdirectory entry.  TYPE and NAME are pointers to higher level
1264    IDs, or NULL.  LANGUAGE is a pointer to the current language.
1265    LEVEL is the level in the tree.  */
1266
1267 static void
1268 write_rc_subdir (e, re, type, name, language, level)
1269      FILE *e;
1270      const struct res_entry *re;
1271      const struct res_id *type;
1272      const struct res_id *name;
1273      int *language;
1274      int level;
1275 {
1276   fprintf (e, "\n");
1277   switch (level)
1278     {
1279     case 1:
1280       fprintf (e, "// Type: ");
1281       if (re->id.named)
1282         res_id_print (e, re->id, 1);
1283       else
1284         {
1285           const char *s;
1286
1287           switch (re->id.u.id)
1288             {
1289             case RT_CURSOR: s = "cursor"; break;
1290             case RT_BITMAP: s = "bitmap"; break;
1291             case RT_ICON: s = "icon"; break;
1292             case RT_MENU: s = "menu"; break;
1293             case RT_DIALOG: s = "dialog"; break;
1294             case RT_STRING: s = "stringtable"; break;
1295             case RT_FONTDIR: s = "fontdir"; break;
1296             case RT_FONT: s = "font"; break;
1297             case RT_ACCELERATOR: s = "accelerators"; break;
1298             case RT_RCDATA: s = "rcdata"; break;
1299             case RT_MESSAGETABLE: s = "messagetable"; break;
1300             case RT_GROUP_CURSOR: s = "group cursor"; break;
1301             case RT_GROUP_ICON: s = "group icon"; break;
1302             case RT_VERSION: s = "version"; break;
1303             case RT_DLGINCLUDE: s = "dlginclude"; break;
1304             case RT_PLUGPLAY: s = "plugplay"; break;
1305             case RT_VXD: s = "vxd"; break;
1306             case RT_ANICURSOR: s = "anicursor"; break;
1307             case RT_ANIICON: s = "aniicon"; break;
1308             default: s = NULL; break;
1309             }
1310
1311           if (s != NULL)
1312             fprintf (e, "%s", s);
1313           else
1314             res_id_print (e, re->id, 1);
1315         }
1316       fprintf (e, "\n");
1317       break;
1318
1319     case 2:
1320       fprintf (e, "// Name: ");
1321       res_id_print (e, re->id, 1);
1322       fprintf (e, "\n");
1323       break;
1324
1325     case 3:
1326       fprintf (e, "// Language: ");
1327       res_id_print (e, re->id, 1);
1328       fprintf (e, "\n");
1329       break;
1330
1331     default:
1332       fprintf (e, "// Level %d: ", level);
1333       res_id_print (e, re->id, 1);
1334       fprintf (e, "\n");
1335     }           
1336
1337   write_rc_directory (e, re->u.dir, type, name, language, level + 1);
1338 }
1339
1340 /* Write out a single resource.  E is the file to write to.  TYPE is a
1341    pointer to the type of the resource.  NAME is a pointer to the name
1342    of the resource; it will be NULL if there is a level mismatch.  RES
1343    is the resource data.  LANGUAGE is a pointer to the current
1344    language.  */
1345
1346 static void
1347 write_rc_resource (e, type, name, res, language)
1348      FILE *e;
1349      const struct res_id *type;
1350      const struct res_id *name;
1351      const struct res_resource *res;
1352      int *language;
1353 {
1354   const char *s;
1355   int rt;
1356   int menuex = 0;
1357
1358   fprintf (e, "\n");
1359
1360   switch (res->type)
1361     {
1362     default:
1363       abort ();
1364
1365     case RES_TYPE_ACCELERATOR:
1366       s = "ACCELERATOR";
1367       rt = RT_ACCELERATOR;
1368       break;
1369
1370     case RES_TYPE_BITMAP:
1371       s = "BITMAP";
1372       rt = RT_BITMAP;
1373       break;
1374
1375     case RES_TYPE_CURSOR:
1376       s = "CURSOR";
1377       rt = RT_CURSOR;
1378       break;
1379
1380     case RES_TYPE_GROUP_CURSOR:
1381       s = "GROUP_CURSOR";
1382       rt = RT_GROUP_CURSOR;
1383       break;
1384
1385     case RES_TYPE_DIALOG:
1386       if (extended_dialog (res->u.dialog))
1387         s = "DIALOGEX";
1388       else
1389         s = "DIALOG";
1390       rt = RT_DIALOG;
1391       break;
1392
1393     case RES_TYPE_FONT:
1394       s = "FONT";
1395       rt = RT_FONT;
1396       break;
1397
1398     case RES_TYPE_FONTDIR:
1399       s = "FONTDIR";
1400       rt = RT_FONTDIR;
1401       break;
1402
1403     case RES_TYPE_ICON:
1404       s = "ICON";
1405       rt = RT_ICON;
1406       break;
1407
1408     case RES_TYPE_GROUP_ICON:
1409       s = "GROUP_ICON";
1410       rt = RT_GROUP_ICON;
1411       break;
1412
1413     case RES_TYPE_MENU:
1414       if (extended_menu (res->u.menu))
1415         {
1416           s = "MENUEX";
1417           menuex = 1;
1418         }
1419       else
1420         {
1421           s = "MENU";
1422           menuex = 0;
1423         }
1424       rt = RT_MENU;
1425       break;
1426
1427     case RES_TYPE_MESSAGETABLE:
1428       s = "MESSAGETABLE";
1429       rt = RT_MESSAGETABLE;
1430       break;
1431
1432     case RES_TYPE_RCDATA:
1433       s = "RCDATA";
1434       rt = RT_RCDATA;
1435       break;
1436
1437     case RES_TYPE_STRINGTABLE:
1438       s = "STRINGTABLE";
1439       rt = RT_STRING;
1440       break;
1441
1442     case RES_TYPE_USERDATA:
1443       s = NULL;
1444       rt = 0;
1445       break;
1446
1447     case RES_TYPE_VERSIONINFO:
1448       s = "VERSIONINFO";
1449       rt = RT_VERSION;
1450       break;
1451     }
1452
1453   if (rt != 0
1454       && type != NULL
1455       && (type->named || type->u.id != (unsigned long) rt))
1456     {
1457       fprintf (e, "// Unexpected resource type mismatch: ");
1458       res_id_print (e, *type, 1);
1459       fprintf (e, " != %d", rt);
1460     }
1461
1462   if (res->coff_info.codepage != 0)
1463     fprintf (e, "// Code page: %lu\n", res->coff_info.codepage);
1464   if (res->coff_info.reserved != 0)
1465     fprintf (e, "// COFF reserved value: %lu\n", res->coff_info.reserved);
1466
1467   if (name != NULL)
1468     res_id_print (e, *name, 0);
1469   else
1470     fprintf (e, "??Unknown-Name??");
1471
1472   fprintf (e, " ");
1473   if (s != NULL)
1474     fprintf (e, "%s", s);
1475   else if (type != NULL)
1476     res_id_print (e, *type, 0);
1477   else
1478     fprintf (e, "??Unknown-Type??");
1479
1480   if (res->res_info.memflags != 0)
1481     {
1482       if ((res->res_info.memflags & MEMFLAG_MOVEABLE) != 0)
1483         fprintf (e, " MOVEABLE");
1484       if ((res->res_info.memflags & MEMFLAG_PURE) != 0)
1485         fprintf (e, " PURE");
1486       if ((res->res_info.memflags & MEMFLAG_PRELOAD) != 0)
1487         fprintf (e, " PRELOAD");
1488       if ((res->res_info.memflags & MEMFLAG_DISCARDABLE) != 0)
1489         fprintf (e, " DISCARDABLE");
1490     }
1491
1492   if (res->type == RES_TYPE_DIALOG)
1493     {
1494       fprintf (e, " %d, %d, %d, %d", res->u.dialog->x, res->u.dialog->y,
1495                res->u.dialog->width, res->u.dialog->height);
1496       if (res->u.dialog->ex != NULL
1497           && res->u.dialog->ex->help != 0)
1498         fprintf (e, ", %lu", res->u.dialog->ex->help);
1499     }
1500
1501   fprintf (e, "\n");
1502
1503   if ((res->res_info.language != 0 && res->res_info.language != *language)
1504       || res->res_info.characteristics != 0
1505       || res->res_info.version != 0)
1506     {
1507       int modifiers;
1508
1509       switch (res->type)
1510         {
1511         case RES_TYPE_ACCELERATOR:
1512         case RES_TYPE_DIALOG:
1513         case RES_TYPE_MENU:
1514         case RES_TYPE_RCDATA:
1515         case RES_TYPE_STRINGTABLE:
1516           modifiers = 1;
1517           break;
1518
1519         default:
1520           modifiers = 0;
1521           break;
1522         }
1523
1524       if (res->res_info.language != 0 && res->res_info.language != *language)
1525         fprintf (e, "%sLANGUAGE %d, %d\n",
1526                  modifiers ? "// " : "",
1527                  res->res_info.language & 0xff,
1528                  (res->res_info.language >> 8) & 0xff);
1529       if (res->res_info.characteristics != 0)
1530         fprintf (e, "%sCHARACTERISTICS %lu\n",
1531                  modifiers ? "// " : "",
1532                  res->res_info.characteristics);
1533       if (res->res_info.version != 0)
1534         fprintf (e, "%sVERSION %lu\n",
1535                  modifiers ? "// " : "",
1536                  res->res_info.version);
1537     }
1538
1539   switch (res->type)
1540     {
1541     default:
1542       abort ();
1543
1544     case RES_TYPE_ACCELERATOR:
1545       write_rc_accelerators (e, res->u.acc);
1546       break;
1547
1548     case RES_TYPE_CURSOR:
1549       write_rc_cursor (e, res->u.cursor);
1550       break;
1551
1552     case RES_TYPE_GROUP_CURSOR:
1553       write_rc_group_cursor (e, res->u.group_cursor);
1554       break;
1555
1556     case RES_TYPE_DIALOG:
1557       write_rc_dialog (e, res->u.dialog);
1558       break;
1559
1560     case RES_TYPE_FONTDIR:
1561       write_rc_fontdir (e, res->u.fontdir);
1562       break;
1563
1564     case RES_TYPE_GROUP_ICON:
1565       write_rc_group_icon (e, res->u.group_icon);
1566       break;
1567
1568     case RES_TYPE_MENU:
1569       write_rc_menu (e, res->u.menu, menuex);
1570       break;
1571
1572     case RES_TYPE_RCDATA:
1573       write_rc_rcdata (e, res->u.rcdata, 0);
1574       break;
1575
1576     case RES_TYPE_STRINGTABLE:
1577       write_rc_stringtable (e, name, res->u.stringtable);
1578       break;
1579
1580     case RES_TYPE_USERDATA:
1581       write_rc_rcdata (e, res->u.userdata, 0);
1582       break;
1583
1584     case RES_TYPE_VERSIONINFO:
1585       write_rc_versioninfo (e, res->u.versioninfo);
1586       break;
1587
1588     case RES_TYPE_BITMAP:
1589     case RES_TYPE_FONT:
1590     case RES_TYPE_ICON:
1591     case RES_TYPE_MESSAGETABLE:
1592       write_rc_filedata (e, res->u.data.length, res->u.data.data);
1593       break;
1594     }
1595 }
1596
1597 /* Write out accelerator information.  */
1598
1599 static void
1600 write_rc_accelerators (e, accelerators)
1601      FILE *e;
1602      const struct accelerator *accelerators;
1603 {
1604   const struct accelerator *acc;
1605
1606   fprintf (e, "BEGIN\n");
1607   for (acc = accelerators; acc != NULL; acc = acc->next)
1608     {
1609       int printable;
1610
1611       fprintf (e, "  ");
1612
1613       if ((acc->key & 0x7f) == acc->key
1614           && isprint ((unsigned char) acc->key)
1615           && (acc->flags & ACC_VIRTKEY) == 0)
1616         {
1617           fprintf (e, "\"%c\"", acc->key);
1618           printable = 1;
1619         }
1620       else
1621         {
1622           fprintf (e, "%d", acc->key);
1623           printable = 0;
1624         }
1625
1626       fprintf (e, ", %d", acc->id);
1627
1628       if (! printable)
1629         {
1630           if ((acc->flags & ACC_VIRTKEY) != 0)
1631             fprintf (e, ", VIRTKEY");
1632           else
1633             fprintf (e, ", ASCII");
1634         }
1635
1636       if ((acc->flags & ACC_SHIFT) != 0)
1637         fprintf (e, ", SHIFT");
1638       if ((acc->flags & ACC_CONTROL) != 0)
1639         fprintf (e, ", CONTROL");
1640       if ((acc->flags & ACC_ALT) != 0)
1641         fprintf (e, ", ALT");
1642
1643       fprintf (e, "\n");
1644     }
1645
1646   fprintf (e, "END\n");
1647 }
1648
1649 /* Write out cursor information.  This would normally be in a separate
1650    file, which the rc file would include.  */
1651
1652 static void
1653 write_rc_cursor (e, cursor)
1654      FILE *e;
1655      const struct cursor *cursor;
1656 {
1657   fprintf (e, "// Hotspot: x: %d; y: %d\n", cursor->xhotspot,
1658            cursor->yhotspot);
1659   write_rc_filedata (e, cursor->length, cursor->data);
1660 }
1661
1662 /* Write out group cursor data.  This would normally be built from the
1663    cursor data.  */
1664
1665 static void
1666 write_rc_group_cursor (e, group_cursor)
1667      FILE *e;
1668      const struct group_cursor *group_cursor;
1669 {
1670   const struct group_cursor *gc;
1671
1672   for (gc = group_cursor; gc != NULL; gc = gc->next)
1673     {
1674       fprintf (e, "// width: %d; height %d; planes %d; bits %d\n",
1675              gc->width, gc->height, gc->planes, gc->bits);
1676       fprintf (e, "// data bytes: %lu; index: %d\n",
1677                gc->bytes, gc->index);
1678     }
1679 }
1680
1681 /* Write dialog data.  */
1682
1683 static void
1684 write_rc_dialog (e, dialog)
1685      FILE *e;
1686      const struct dialog *dialog;
1687 {
1688   const struct dialog_control *control;
1689
1690   if (dialog->style != 0)
1691     fprintf (e, "STYLE 0x%lx\n", dialog->style);
1692   if (dialog->exstyle != 0)
1693     fprintf (e, "EXSTYLE 0x%lx\n", dialog->exstyle);
1694   if ((dialog->class.named && dialog->class.u.n.length > 0)
1695       || dialog->class.u.id != 0)
1696     {
1697       fprintf (e, "CLASS ");
1698       res_id_print (e, dialog->class, 0);
1699       fprintf (e, "\n");
1700     }
1701   if (dialog->caption != NULL)
1702     {
1703       fprintf (e, "CAPTION \"");
1704       unicode_print (e, dialog->caption, -1);
1705       fprintf (e, "\"\n");
1706     }
1707   if ((dialog->menu.named && dialog->menu.u.n.length > 0)
1708       || dialog->menu.u.id != 0)
1709     {
1710       fprintf (e, "MENU ");
1711       res_id_print (e, dialog->menu, 0);
1712       fprintf (e, "\n");
1713     }
1714   if (dialog->font != NULL)
1715     {
1716       fprintf (e, "FONT %d, \"", dialog->pointsize);
1717       unicode_print (e, dialog->font, -1);
1718       fprintf (e, "\"");
1719       if (dialog->ex != NULL
1720           && (dialog->ex->weight != 0 || dialog->ex->italic != 0))
1721         fprintf (e, ", %d, %d", dialog->ex->weight, dialog->ex->italic);
1722       fprintf (e, "\n");
1723     }
1724
1725   fprintf (e, "BEGIN\n");
1726
1727   for (control = dialog->controls; control != NULL; control = control->next)
1728     write_rc_dialog_control (e, control);
1729
1730   fprintf (e, "END\n");
1731 }
1732
1733 /* For each predefined control keyword, this table provides the class
1734    and the style.  */
1735
1736 struct control_info
1737 {
1738   const char *name;
1739   unsigned short class;
1740   unsigned long style;
1741 };
1742
1743 static const struct control_info control_info[] =
1744 {
1745   { "AUTO3STATE", CTL_BUTTON, BS_AUTO3STATE },
1746   { "AUTOCHECKBOX", CTL_BUTTON, BS_AUTOCHECKBOX },
1747   { "AUTORADIOBUTTON", CTL_BUTTON, BS_AUTORADIOBUTTON },
1748   { "CHECKBOX", CTL_BUTTON, BS_CHECKBOX },
1749   { "COMBOBOX", CTL_COMBOBOX, (unsigned long) -1 },
1750   { "CTEXT", CTL_STATIC, SS_CENTER },
1751   { "DEFPUSHBUTTON", CTL_BUTTON, BS_DEFPUSHBUTTON },
1752   { "EDITTEXT", CTL_EDIT, (unsigned long) -1 },
1753   { "GROUPBOX", CTL_BUTTON, BS_GROUPBOX },
1754   { "ICON", CTL_STATIC, SS_ICON },
1755   { "LISTBOX", CTL_LISTBOX, (unsigned long) -1 },
1756   { "LTEXT", CTL_STATIC, SS_LEFT },
1757   { "PUSHBOX", CTL_BUTTON, BS_PUSHBOX },
1758   { "PUSHBUTTON", CTL_BUTTON, BS_PUSHBUTTON },
1759   { "RADIOBUTTON", CTL_BUTTON, BS_RADIOBUTTON },
1760   { "RTEXT", CTL_STATIC, SS_RIGHT },
1761   { "SCROLLBAR", CTL_SCROLLBAR, (unsigned long) -1 },
1762   { "STATE3", CTL_BUTTON, BS_3STATE },
1763   /* It's important that USERBUTTON come after all the other button
1764      types, so that it won't be matched too early.  */
1765   { "USERBUTTON", CTL_BUTTON, (unsigned long) -1 },
1766   { NULL, 0, 0 }
1767 };
1768
1769 /* Write a dialog control.  */
1770
1771 static void
1772 write_rc_dialog_control (e, control)
1773      FILE *e;
1774      const struct dialog_control *control;
1775 {
1776   const struct control_info *ci;
1777
1778   fprintf (e, "  ");
1779
1780   if (control->class.named)
1781     ci = NULL;
1782   else
1783     {
1784       for (ci = control_info; ci->name != NULL; ++ci)
1785         if (ci->class == control->class.u.id
1786             && (ci->style == (unsigned long) -1
1787                 || ci->style == (control->style & 0xff)))
1788           break;
1789     }
1790   if (ci == NULL)
1791     fprintf (e, "CONTROL");
1792   else if (ci->name != NULL)
1793     fprintf (e, "%s", ci->name);
1794   else
1795     fprintf (e, "CONTROL");
1796   
1797   if (control->text.named || control->text.u.id != 0)
1798     {
1799       fprintf (e, " ");
1800       res_id_print (e, control->text, 1);
1801       fprintf (e, ",");
1802     }
1803
1804   fprintf (e, " %d, ", control->id);
1805
1806   if (ci == NULL)
1807     {
1808       if (control->class.named)
1809         fprintf (e, "\"");
1810       res_id_print (e, control->class, 0);
1811       if (control->class.named)
1812         fprintf (e, "\"");
1813       fprintf (e, ", 0x%lx, ", control->style);
1814     }
1815
1816   fprintf (e, "%d, %d", control->x, control->y);
1817
1818   if (control->style != SS_ICON
1819       || control->exstyle != 0
1820       || control->width != 0
1821       || control->height != 0
1822       || control->help != 0)
1823     {
1824       fprintf (e, ", %d, %d", control->width, control->height);
1825
1826       /* FIXME: We don't need to print the style if it is the default.
1827          More importantly, in certain cases we actually need to turn
1828          off parts of the forced style, by using NOT.  */
1829       fprintf (e, ", 0x%lx", control->style);
1830
1831       if (control->exstyle != 0 || control->help != 0)
1832         fprintf (e, ", 0x%lx, %lu", control->exstyle, control->help);
1833     }
1834
1835   fprintf (e, "\n");
1836
1837   if (control->data != NULL)
1838     write_rc_rcdata (e, control->data, 2);
1839 }
1840
1841 /* Write out font directory data.  This would normally be built from
1842    the font data.  */
1843
1844 static void
1845 write_rc_fontdir (e, fontdir)
1846      FILE *e;
1847      const struct fontdir *fontdir;
1848 {
1849   const struct fontdir *fc;
1850
1851   for (fc = fontdir; fc != NULL; fc = fc->next)
1852     {
1853       fprintf (e, "// Font index: %d\n", fc->index);
1854       write_rc_filedata (e, fc->length, fc->data);
1855     }
1856 }
1857
1858 /* Write out group icon data.  This would normally be built from the
1859    icon data.  */
1860
1861 static void
1862 write_rc_group_icon (e, group_icon)
1863      FILE *e;
1864      const struct group_icon *group_icon;
1865 {
1866   const struct group_icon *gi;
1867
1868   for (gi = group_icon; gi != NULL; gi = gi->next)
1869     {
1870       fprintf (e, "// width: %d; height %d; colors: %d; planes %d; bits %d\n",
1871                gi->width, gi->height, gi->colors, gi->planes, gi->bits);
1872       fprintf (e, "// data bytes: %lu; index: %d\n",
1873                gi->bytes, gi->index);
1874     }
1875 }
1876
1877 /* Write out a menu resource.  */
1878
1879 static void
1880 write_rc_menu (e, menu, menuex)
1881      FILE *e;
1882      const struct menu *menu;
1883      int menuex;
1884 {
1885   if (menu->help != 0)
1886     fprintf (e, "// Help ID: %lu\n", menu->help);
1887   write_rc_menuitems (e, menu->items, menuex, 0);
1888 }
1889
1890 /* Write out menuitems.  */
1891
1892 static void
1893 write_rc_menuitems (e, menuitems, menuex, ind)
1894      FILE *e;
1895      const struct menuitem *menuitems;
1896      int menuex;
1897      int ind;
1898 {
1899   const struct menuitem *mi;
1900
1901   indent (e, ind);
1902   fprintf (e, "BEGIN\n");
1903
1904   for (mi = menuitems; mi != NULL; mi = mi->next)
1905     {
1906       indent (e, ind + 2);
1907
1908       if (mi->popup == NULL)
1909         fprintf (e, "MENUITEM");
1910       else
1911         fprintf (e, "POPUP");
1912
1913       if (! menuex
1914           && mi->popup == NULL
1915           && mi->text == NULL
1916           && mi->type == 0
1917           && mi->id == 0)
1918         {
1919           fprintf (e, " SEPARATOR\n");
1920           continue;
1921         }
1922
1923       if (mi->text == NULL)
1924         fprintf (e, " \"\"");
1925       else
1926         {
1927           fprintf (e, " \"");
1928           unicode_print (e, mi->text, -1);
1929           fprintf (e, "\"");
1930         }
1931
1932       if (! menuex)
1933         {
1934           if (mi->popup == NULL)
1935             fprintf (e, ", %d", mi->id);
1936
1937           if ((mi->type & MENUITEM_CHECKED) != 0)
1938             fprintf (e, ", CHECKED");
1939           if ((mi->type & MENUITEM_GRAYED) != 0)
1940             fprintf (e, ", GRAYED");
1941           if ((mi->type & MENUITEM_HELP) != 0)
1942             fprintf (e, ", HELP");
1943           if ((mi->type & MENUITEM_INACTIVE) != 0)
1944             fprintf (e, ", INACTIVE");
1945           if ((mi->type & MENUITEM_MENUBARBREAK) != 0)
1946             fprintf (e, ", MENUBARBREAK");
1947           if ((mi->type & MENUITEM_MENUBREAK) != 0)
1948             fprintf (e, ", MENUBREAK");
1949         }
1950       else
1951         {
1952           if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0)
1953             {
1954               fprintf (e, ", %d", mi->id);
1955               if (mi->type != 0 || mi->state != 0 || mi->help != 0)
1956                 {
1957                   fprintf (e, ", %lu", mi->type);
1958                   if (mi->state != 0 || mi->help != 0)
1959                     {
1960                       fprintf (e, ", %lu", mi->state);
1961                       if (mi->help != 0)
1962                         fprintf (e, ", %lu", mi->help);
1963                     }
1964                 }
1965             }
1966         }
1967
1968       fprintf (e, "\n");
1969
1970       if (mi->popup != NULL)
1971         write_rc_menuitems (e, mi->popup, menuex, ind + 2);
1972     }
1973
1974   indent (e, ind);
1975   fprintf (e, "END\n");
1976 }
1977
1978 /* Write out an rcdata resource.  This is also used for other types of
1979    resources that need to print arbitrary data.  */
1980
1981 static void
1982 write_rc_rcdata (e, rcdata, ind)
1983      FILE *e;
1984      const struct rcdata_item *rcdata;
1985      int ind;
1986 {
1987   const struct rcdata_item *ri;
1988
1989   indent (e, ind);
1990   fprintf (e, "BEGIN\n");
1991
1992   for (ri = rcdata; ri != NULL; ri = ri->next)
1993     {
1994       if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0)
1995         continue;
1996
1997       indent (e, ind + 2);
1998
1999       switch (ri->type)
2000         {
2001         default:
2002           abort ();
2003
2004         case RCDATA_WORD:
2005           fprintf (e, "%d", ri->u.word);
2006           break;
2007
2008         case RCDATA_DWORD:
2009           fprintf (e, "%luL", ri->u.dword);
2010           break;
2011
2012         case RCDATA_STRING:
2013           {
2014             const char *s;
2015             unsigned long i;
2016
2017             fprintf (e, "\"");
2018             s = ri->u.string.s;
2019             for (i = 0; i < ri->u.string.length; i++)
2020               {
2021                 if (isprint ((unsigned char) *s))
2022                   putc (*s, e);
2023                 else
2024                   fprintf (e, "\\%03o", *s);
2025               }
2026             fprintf (e, "\"");
2027             break;
2028           }
2029
2030         case RCDATA_WSTRING:
2031           fprintf (e, "L\"");
2032           unicode_print (e, ri->u.wstring.w, ri->u.wstring.length);
2033           fprintf (e, "\"");
2034           break;
2035
2036         case RCDATA_BUFFER:
2037           {
2038             unsigned long i;
2039             int first;
2040
2041             /* Assume little endian data.  */
2042
2043             first = 1;
2044             for (i = 0; i + 3 < ri->u.buffer.length; i += 4)
2045               {
2046                 unsigned long l;
2047
2048                 l = ((((((ri->u.buffer.data[i + 3] << 8)
2049                          | ri->u.buffer.data[i + 2]) << 8)
2050                        | ri->u.buffer.data[i + 1]) << 8)
2051                      | ri->u.buffer.data[i]);
2052                 if (first)
2053                   first = 0;
2054                 else
2055                   {
2056                     fprintf (e, ",\n");
2057                     indent (e, ind + 2);
2058                   }
2059                 fprintf (e, "%luL", l);
2060               }
2061
2062             if (i + 1 < ri->u.buffer.length)
2063               {
2064                 int i;
2065
2066                 i = (ri->u.buffer.data[i + 1] << 8) | ri->u.buffer.data[i];
2067                 if (first)
2068                   first = 0;
2069                 else
2070                   {
2071                     fprintf (e, ",\n");
2072                     indent (e, ind + 2);
2073                   }
2074                 fprintf (e, "%d", i);
2075                 i += 2;
2076               }
2077
2078             if (i < ri->u.buffer.length)
2079               {
2080                 if (first)
2081                   first = 0;
2082                 else
2083                   {
2084                     fprintf (e, ",\n");
2085                     indent (e, ind + 2);
2086                   }
2087                 if ((ri->u.buffer.data[i] & 0x7f) == ri->u.buffer.data[i]
2088                     && isprint (ri->u.buffer.data[i]))
2089                   fprintf (e, "\"%c\"", ri->u.buffer.data[i]);
2090                 else
2091                   fprintf (e, "\"\%03o\"", ri->u.buffer.data[i]);
2092               }
2093
2094             break;
2095           }
2096         }
2097
2098       if (ri->next != NULL)
2099         fprintf (e, ",");
2100       fprintf (e, "\n");
2101     }
2102
2103   indent (e, ind);
2104   fprintf (e, "END\n");
2105 }
2106
2107 /* Write out a stringtable resource.  */
2108
2109 static void
2110 write_rc_stringtable (e, name, stringtable)
2111      FILE *e;
2112      const struct res_id *name;
2113      const struct stringtable *stringtable;
2114 {
2115   unsigned long offset;
2116   int i;
2117
2118   if (name != NULL && ! name->named)
2119     offset = (name->u.id - 1) << 4;
2120   else
2121     {
2122       fprintf (e, "// %s string table name\n",
2123                name == NULL ? "Missing" : "Invalid");
2124       offset = 0;
2125     }
2126
2127   fprintf (e, "BEGIN\n");
2128
2129   for (i = 0; i < 16; i++)
2130     {
2131       if (stringtable->strings[i].length != 0)
2132         {
2133           fprintf (e, "  %lu, \"", offset + i);
2134           unicode_print (e, stringtable->strings[i].string,
2135                          stringtable->strings[i].length);
2136           fprintf (e, "\"\n");
2137         }
2138     }
2139
2140   fprintf (e, "END\n");
2141 }
2142
2143 /* Write out a versioninfo resource.  */
2144
2145 static void
2146 write_rc_versioninfo (e, versioninfo)
2147      FILE *e;
2148      const struct versioninfo *versioninfo;
2149 {
2150   const struct fixed_versioninfo *f;
2151   const struct ver_info *vi;
2152
2153   f = versioninfo->fixed;
2154   if (f->file_version_ms != 0 || f->file_version_ls != 0)
2155     fprintf (e, " FILEVERSION %lu, %lu, %lu, %lu\n",
2156              (f->file_version_ms >> 16) & 0xffff,
2157              f->file_version_ms & 0xffff,
2158              (f->file_version_ls >> 16) & 0xffff,
2159              f->file_version_ls & 0xffff);
2160   if (f->product_version_ms != 0 || f->product_version_ls != 0)
2161     fprintf (e, " PRODUCTVERSION %lu, %lu, %lu, %lu\n",
2162              (f->product_version_ms >> 16) & 0xffff,
2163              f->product_version_ms & 0xffff,
2164              (f->product_version_ls >> 16) & 0xffff,
2165              f->product_version_ls & 0xffff);
2166   if (f->file_flags_mask != 0)
2167     fprintf (e, " FILEFLAGSMASK 0x%lx\n", f->file_flags_mask);
2168   if (f->file_flags != 0)
2169     fprintf (e, " FILEFLAGS 0x%lx\n", f->file_flags);
2170   if (f->file_os != 0)
2171     fprintf (e, " FILEOS 0x%lx\n", f->file_os);
2172   if (f->file_type != 0)
2173     fprintf (e, " FILETYPE 0x%lx\n", f->file_type);
2174   if (f->file_subtype != 0)
2175     fprintf (e, " FILESUBTYPE 0x%lx\n", f->file_subtype);
2176   if (f->file_date_ms != 0 || f->file_date_ls != 0)
2177     fprintf (e, "// Date: %lu, %lu\n", f->file_date_ms, f->file_date_ls);
2178
2179   fprintf (e, "BEGIN\n");
2180
2181   for (vi = versioninfo->var; vi != NULL; vi = vi->next)
2182     {
2183       switch (vi->type)
2184         {
2185         case VERINFO_STRING:
2186           {
2187             const struct ver_stringinfo *vs;
2188
2189             fprintf (e, "  BLOCK \"StringFileInfo\"\n");
2190             fprintf (e, "  BEGIN\n");
2191             fprintf (e, "    BLOCK \"");
2192             unicode_print (e, vi->u.string.language, -1);
2193             fprintf (e, "\"\n");
2194             fprintf (e, "    BEGIN\n");
2195
2196             for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
2197               {
2198                 fprintf (e, "      VALUE \"");
2199                 unicode_print (e, vs->key, -1);
2200                 fprintf (e, "\", \"");
2201                 unicode_print (e, vs->value, -1);
2202                 fprintf (e, "\"\n");
2203               }
2204
2205             fprintf (e, "    END\n");
2206             fprintf (e, "  END\n");
2207             break;
2208           }
2209
2210         case VERINFO_VAR:
2211           {
2212             const struct ver_varinfo *vv;
2213
2214             fprintf (e, "  BLOCK \"VarFileInfo\"\n");
2215             fprintf (e, "  BEGIN\n");
2216             fprintf (e, "    VALUE \"");
2217             unicode_print (e, vi->u.var.key, -1);
2218             fprintf (e, "\"");
2219
2220             for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
2221               fprintf (e, ", 0x%x, %d", (unsigned int) vv->language,
2222                        vv->charset);
2223
2224             fprintf (e, "\n  END\n");
2225
2226             break;
2227           }
2228         }
2229     }
2230
2231   fprintf (e, "END\n");
2232 }
2233
2234 /* Write out data which would normally be read from a file.  */
2235
2236 static void
2237 write_rc_filedata (e, length, data)
2238      FILE *e;
2239      unsigned long length;
2240      const unsigned char *data;
2241 {
2242   unsigned long i;
2243
2244   for (i = 0; i + 15 < length; i += 16)
2245     {
2246       fprintf (e, "// %4lx: ", i);
2247       fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x ",
2248                data[i + 0], data[i + 1], data[i + 2], data[i + 3],
2249                data[i + 4], data[i + 5], data[i + 6], data[i + 7]);
2250       fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
2251                data[i +  8], data[i +  9], data[i + 10], data[i + 11],
2252                data[i + 12], data[i + 13], data[i + 14], data[i + 15]);
2253     }
2254
2255   if (i < length)
2256     {
2257       fprintf (e, "// %4lx:", i);
2258       while (i < length)
2259         {
2260           fprintf (e, " %02x", data[i]);
2261           ++i;
2262         }
2263       fprintf (e, "\n");
2264     }
2265 }