resrc.c revision 38889
1234285Sdim/* resrc.c -- read and write Windows rc files.
2234285Sdim   Copyright 1997, 1998 Free Software Foundation, Inc.
3234285Sdim   Written by Ian Lance Taylor, Cygnus Support.
4234285Sdim
5234285Sdim   This file is part of GNU Binutils.
6234285Sdim
7234285Sdim   This program is free software; you can redistribute it and/or modify
8234285Sdim   it under the terms of the GNU General Public License as published by
9234285Sdim   the Free Software Foundation; either version 2 of the License, or
10234285Sdim   (at your option) any later version.
11234285Sdim
12234285Sdim   This program is distributed in the hope that it will be useful,
13234285Sdim   but WITHOUT ANY WARRANTY; without even the implied warranty of
14234285Sdim   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15234285Sdim   GNU General Public License for more details.
16234285Sdim
17234285Sdim   You should have received a copy of the GNU General Public License
18234285Sdim   along with this program; if not, write to the Free Software
19234285Sdim   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20245431Sdim   02111-1307, USA.  */
21245431Sdim
22234285Sdim/* This file contains functions that read and write Windows rc files.
23234285Sdim   These are text files that represent resources.  */
24234285Sdim
25234285Sdim#include "bfd.h"
26234285Sdim#include "bucomm.h"
27234285Sdim#include "libiberty.h"
28234285Sdim#include "windres.h"
29234285Sdim
30245431Sdim#include <assert.h>
31245431Sdim#include <ctype.h>
32234285Sdim#include <sys/stat.h>
33234285Sdim
34234285Sdim#if defined (_WIN32) && ! defined (__CYGWIN32__)
35234285Sdim#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
46struct 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
79char *rc_filename;
80
81/* The line number in the rc file.  */
82
83int rc_lineno;
84
85/* The pipe we are reading from, so that we can close it if we exit.  */
86
87static FILE *cpp_pipe;
88
89/* As we read the rc file, we attach information to this structure.  */
90
91static struct res_directory *resources;
92
93/* The number of cursor resources we have written out.  */
94
95static int cursors;
96
97/* The number of font resources we have written out.  */
98
99static int fonts;
100
101/* Font directory information.  */
102
103struct fontdir *fontdirs;
104
105/* Resource info to use for fontdirs.  */
106
107struct res_res_info fontdirs_resinfo;
108
109/* The number of icon resources we have written out.  */
110
111static int icons;
112
113/* Local functions.  */
114
115static void close_pipe PARAMS ((void));
116static void unexpected_eof PARAMS ((const char *));
117static int get_word PARAMS ((FILE *, const char *));
118static unsigned long get_long PARAMS ((FILE *, const char *));
119static void get_data
120  PARAMS ((FILE *, unsigned char *, unsigned long, const char *));
121static void define_fontdirs PARAMS ((void));
122
123/* Read an rc file.  */
124
125struct res_directory *
126read_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
177void
178close_pipe ()
179{
180  if (cpp_pipe != NULL)
181    pclose (cpp_pipe);
182}
183
184/* Report an error while reading an rc file.  */
185
186void
187yyerror (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
195void
196rcparse_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
204static void
205unexpected_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
214static int
215get_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
231static unsigned long
232get_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
252static void
253get_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
268/* Define an accelerator resource.  */
269
270void
271define_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_ACCELERATORS, 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
291void
292define_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
335void
336define_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
455void
456define_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
477struct dialog_control *
478define_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
517void
518define_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
605static void
606define_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
627void
628define_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
746void
747define_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
768struct menuitem *
769define_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
795void
796define_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
832void
833define_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
849struct rcdata_item *
850define_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
870struct rcdata_item *
871define_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
888void
889define_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
925void
926define_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
948void
949define_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
993void
994define_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
1013struct ver_info *
1014append_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
1036struct ver_info *
1037append_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
1059struct ver_stringinfo *
1060append_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
1081struct ver_varinfo *
1082append_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
1101/* Local functions used to write out an rc file.  */
1102
1103static void indent PARAMS ((FILE *, int));
1104static void write_rc_directory
1105  PARAMS ((FILE *, const struct res_directory *, const struct res_id *,
1106	   const struct res_id *, int *, int));
1107static void write_rc_subdir
1108  PARAMS ((FILE *, const struct res_entry *, const struct res_id *,
1109	   const struct res_id *, int *, int));
1110static void write_rc_resource
1111  PARAMS ((FILE *, const struct res_id *, const struct res_id *,
1112	   const struct res_resource *, int *));
1113static void write_rc_accelerators
1114  PARAMS ((FILE *, const struct accelerator *));
1115static void write_rc_cursor PARAMS ((FILE *, const struct cursor *));
1116static void write_rc_group_cursor
1117  PARAMS ((FILE *, const struct group_cursor *));
1118static void write_rc_dialog PARAMS ((FILE *, const struct dialog *));
1119static void write_rc_dialog_control
1120  PARAMS ((FILE *, const struct dialog_control *));
1121static void write_rc_fontdir PARAMS ((FILE *, const struct fontdir *));
1122static void write_rc_group_icon PARAMS ((FILE *, const struct group_icon *));
1123static void write_rc_menu PARAMS ((FILE *, const struct menu *, int));
1124static void write_rc_menuitems
1125  PARAMS ((FILE *, const struct menuitem *, int, int));
1126static void write_rc_rcdata PARAMS ((FILE *, const struct rcdata_item *, int));
1127static void write_rc_stringtable
1128  PARAMS ((FILE *, const struct res_id *, const struct stringtable *));
1129static void write_rc_versioninfo PARAMS ((FILE *, const struct versioninfo *));
1130static void write_rc_filedata
1131  PARAMS ((FILE *, unsigned long, const unsigned char *));
1132
1133/* Indent a given number of spaces.  */
1134
1135static void
1136indent (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
1156void
1157write_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
1184static void
1185write_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 != *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
1267static void
1268write_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_ACCELERATORS: 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
1346static void
1347write_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_ACCELERATORS;
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 != 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
1599static void
1600write_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
1652static void
1653write_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
1665static void
1666write_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
1683static void
1684write_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
1736struct control_info
1737{
1738  const char *name;
1739  unsigned short class;
1740  unsigned long style;
1741};
1742
1743static 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
1771static void
1772write_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
1791  if (ci->name != NULL)
1792    fprintf (e, "%s", ci->name);
1793  else
1794    fprintf (e, "CONTROL");
1795
1796  if (control->text.named || control->text.u.id != 0)
1797    {
1798      fprintf (e, " ");
1799      res_id_print (e, control->text, 1);
1800      fprintf (e, ",");
1801    }
1802
1803  fprintf (e, " %d, ", control->id);
1804
1805  if (ci->name == NULL)
1806    {
1807      res_id_print (e, control->class, 0);
1808      fprintf (e, ", 0x%lx, ", control->style);
1809    }
1810
1811  fprintf (e, "%d, %d", control->x, control->y);
1812
1813  if (control->style != SS_ICON
1814      || control->exstyle != 0
1815      || control->width != 0
1816      || control->height != 0
1817      || control->help != 0)
1818    {
1819      fprintf (e, ", %d, %d", control->width, control->height);
1820
1821      /* FIXME: We don't need to print the style if it is the default.
1822	 More importantly, in certain cases we actually need to turn
1823	 off parts of the forced style, by using NOT.  */
1824      fprintf (e, ", 0x%lx", control->style);
1825
1826      if (control->exstyle != 0 || control->help != 0)
1827	fprintf (e, ", 0x%lx, %lu", control->exstyle, control->help);
1828    }
1829
1830  fprintf (e, "\n");
1831
1832  if (control->data != NULL)
1833    write_rc_rcdata (e, control->data, 2);
1834}
1835
1836/* Write out font directory data.  This would normally be built from
1837   the font data.  */
1838
1839static void
1840write_rc_fontdir (e, fontdir)
1841     FILE *e;
1842     const struct fontdir *fontdir;
1843{
1844  const struct fontdir *fc;
1845
1846  for (fc = fontdir; fc != NULL; fc = fc->next)
1847    {
1848      fprintf (e, "// Font index: %d\n", fc->index);
1849      write_rc_filedata (e, fc->length, fc->data);
1850    }
1851}
1852
1853/* Write out group icon data.  This would normally be built from the
1854   icon data.  */
1855
1856static void
1857write_rc_group_icon (e, group_icon)
1858     FILE *e;
1859     const struct group_icon *group_icon;
1860{
1861  const struct group_icon *gi;
1862
1863  for (gi = group_icon; gi != NULL; gi = gi->next)
1864    {
1865      fprintf (e, "// width: %d; height %d; colors: %d; planes %d; bits %d\n",
1866	       gi->width, gi->height, gi->colors, gi->planes, gi->bits);
1867      fprintf (e, "// data bytes: %lu; index: %d\n",
1868	       gi->bytes, gi->index);
1869    }
1870}
1871
1872/* Write out a menu resource.  */
1873
1874static void
1875write_rc_menu (e, menu, menuex)
1876     FILE *e;
1877     const struct menu *menu;
1878     int menuex;
1879{
1880  if (menu->help != 0)
1881    fprintf (e, "// Help ID: %lu\n", menu->help);
1882  write_rc_menuitems (e, menu->items, menuex, 0);
1883}
1884
1885/* Write out menuitems.  */
1886
1887static void
1888write_rc_menuitems (e, menuitems, menuex, ind)
1889     FILE *e;
1890     const struct menuitem *menuitems;
1891     int menuex;
1892     int ind;
1893{
1894  const struct menuitem *mi;
1895
1896  indent (e, ind);
1897  fprintf (e, "BEGIN\n");
1898
1899  for (mi = menuitems; mi != NULL; mi = mi->next)
1900    {
1901      indent (e, ind + 2);
1902
1903      if (mi->popup == NULL)
1904	fprintf (e, "MENUITEM");
1905      else
1906	fprintf (e, "POPUP");
1907
1908      if (! menuex
1909	  && mi->popup == NULL
1910	  && mi->text == NULL
1911	  && mi->type == 0
1912	  && mi->id == 0)
1913	{
1914	  fprintf (e, " SEPARATOR\n");
1915	  continue;
1916	}
1917
1918      if (mi->text == NULL)
1919	fprintf (e, " \"\"");
1920      else
1921	{
1922	  fprintf (e, " \"");
1923	  unicode_print (e, mi->text, -1);
1924	  fprintf (e, "\"");
1925	}
1926
1927      if (! menuex)
1928	{
1929	  if (mi->popup == NULL)
1930	    fprintf (e, ", %d", mi->id);
1931
1932	  if ((mi->type & MENUITEM_CHECKED) != 0)
1933	    fprintf (e, ", CHECKED");
1934	  if ((mi->type & MENUITEM_GRAYED) != 0)
1935	    fprintf (e, ", GRAYED");
1936	  if ((mi->type & MENUITEM_HELP) != 0)
1937	    fprintf (e, ", HELP");
1938	  if ((mi->type & MENUITEM_INACTIVE) != 0)
1939	    fprintf (e, ", INACTIVE");
1940	  if ((mi->type & MENUITEM_MENUBARBREAK) != 0)
1941	    fprintf (e, ", MENUBARBREAK");
1942	  if ((mi->type & MENUITEM_MENUBREAK) != 0)
1943	    fprintf (e, ", MENUBREAK");
1944	}
1945      else
1946	{
1947	  if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0)
1948	    {
1949	      fprintf (e, ", %d", mi->id);
1950	      if (mi->type != 0 || mi->state != 0 || mi->help != 0)
1951		{
1952		  fprintf (e, ", %lu", mi->type);
1953		  if (mi->state != 0 || mi->help != 0)
1954		    {
1955		      fprintf (e, ", %lu", mi->state);
1956		      if (mi->help != 0)
1957			fprintf (e, ", %lu", mi->help);
1958		    }
1959		}
1960	    }
1961	}
1962
1963      fprintf (e, "\n");
1964
1965      if (mi->popup != NULL)
1966	write_rc_menuitems (e, mi->popup, menuex, ind + 2);
1967    }
1968
1969  indent (e, ind);
1970  fprintf (e, "END\n");
1971}
1972
1973/* Write out an rcdata resource.  This is also used for other types of
1974   resources that need to print arbitrary data.  */
1975
1976static void
1977write_rc_rcdata (e, rcdata, ind)
1978     FILE *e;
1979     const struct rcdata_item *rcdata;
1980     int ind;
1981{
1982  const struct rcdata_item *ri;
1983
1984  indent (e, ind);
1985  fprintf (e, "BEGIN\n");
1986
1987  for (ri = rcdata; ri != NULL; ri = ri->next)
1988    {
1989      if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0)
1990	continue;
1991
1992      indent (e, ind + 2);
1993
1994      switch (ri->type)
1995	{
1996	default:
1997	  abort ();
1998
1999	case RCDATA_WORD:
2000	  fprintf (e, "%d", ri->u.word);
2001	  break;
2002
2003	case RCDATA_DWORD:
2004	  fprintf (e, "%luL", ri->u.dword);
2005	  break;
2006
2007	case RCDATA_STRING:
2008	  {
2009	    const char *s;
2010	    unsigned long i;
2011
2012	    fprintf (e, "\"");
2013	    s = ri->u.string.s;
2014	    for (i = 0; i < ri->u.string.length; i++)
2015	      {
2016		if (isprint (*s))
2017		  putc (*s, e);
2018		else
2019		  fprintf (e, "\\%03o", *s);
2020	      }
2021	    fprintf (e, "\"");
2022	    break;
2023	  }
2024
2025	case RCDATA_WSTRING:
2026	  fprintf (e, "L\"");
2027	  unicode_print (e, ri->u.wstring.w, ri->u.wstring.length);
2028	  fprintf (e, "\"");
2029	  break;
2030
2031	case RCDATA_BUFFER:
2032	  {
2033	    unsigned long i;
2034	    int first;
2035
2036	    /* Assume little endian data.  */
2037
2038	    first = 1;
2039	    for (i = 0; i + 3 < ri->u.buffer.length; i += 4)
2040	      {
2041		unsigned long l;
2042
2043		l = ((((((ri->u.buffer.data[i + 3] << 8)
2044			 | ri->u.buffer.data[i + 2]) << 8)
2045		       | ri->u.buffer.data[i + 1]) << 8)
2046		     | ri->u.buffer.data[i]);
2047		if (first)
2048		  first = 0;
2049		else
2050		  {
2051		    fprintf (e, ",\n");
2052		    indent (e, ind + 2);
2053		  }
2054		fprintf (e, "%luL", l);
2055	      }
2056
2057	    if (i + 1 < ri->u.buffer.length)
2058	      {
2059		int i;
2060
2061		i = (ri->u.buffer.data[i + 1] << 8) | ri->u.buffer.data[i];
2062		if (first)
2063		  first = 0;
2064		else
2065		  {
2066		    fprintf (e, ",\n");
2067		    indent (e, ind + 2);
2068		  }
2069		fprintf (e, "%d", i);
2070		i += 2;
2071	      }
2072
2073	    if (i < ri->u.buffer.length)
2074	      {
2075		if (first)
2076		  first = 0;
2077		else
2078		  {
2079		    fprintf (e, ",\n");
2080		    indent (e, ind + 2);
2081		  }
2082		if ((ri->u.buffer.data[i] & 0x7f) == ri->u.buffer.data[i]
2083		    && isprint (ri->u.buffer.data[i]))
2084		  fprintf (e, "\"%c\"", ri->u.buffer.data[i]);
2085		else
2086		  fprintf (e, "\"\%03o\"", ri->u.buffer.data[i]);
2087	      }
2088
2089	    break;
2090	  }
2091	}
2092
2093      if (ri->next != NULL)
2094	fprintf (e, ",");
2095      fprintf (e, "\n");
2096    }
2097
2098  indent (e, ind);
2099  fprintf (e, "END\n");
2100}
2101
2102/* Write out a stringtable resource.  */
2103
2104static void
2105write_rc_stringtable (e, name, stringtable)
2106     FILE *e;
2107     const struct res_id *name;
2108     const struct stringtable *stringtable;
2109{
2110  unsigned long offset;
2111  int i;
2112
2113  if (name != NULL && ! name->named)
2114    offset = (name->u.id - 1) << 4;
2115  else
2116    {
2117      fprintf (e, "// %s string table name\n",
2118	       name == NULL ? "Missing" : "Invalid");
2119      offset = 0;
2120    }
2121
2122  fprintf (e, "BEGIN\n");
2123
2124  for (i = 0; i < 16; i++)
2125    {
2126      if (stringtable->strings[i].length != 0)
2127	{
2128	  fprintf (e, "  %lu, \"", offset + i);
2129	  unicode_print (e, stringtable->strings[i].string,
2130			 stringtable->strings[i].length);
2131	  fprintf (e, "\"\n");
2132	}
2133    }
2134
2135  fprintf (e, "END\n");
2136}
2137
2138/* Write out a versioninfo resource.  */
2139
2140static void
2141write_rc_versioninfo (e, versioninfo)
2142     FILE *e;
2143     const struct versioninfo *versioninfo;
2144{
2145  const struct fixed_versioninfo *f;
2146  const struct ver_info *vi;
2147
2148  f = versioninfo->fixed;
2149  if (f->file_version_ms != 0 || f->file_version_ls != 0)
2150    fprintf (e, " FILEVERSION %lu, %lu, %lu, %lu\n",
2151	     (f->file_version_ms >> 16) & 0xffff,
2152	     f->file_version_ms & 0xffff,
2153	     (f->file_version_ls >> 16) & 0xffff,
2154	     f->file_version_ls & 0xffff);
2155  if (f->product_version_ms != 0 || f->product_version_ls != 0)
2156    fprintf (e, " PRODUCTVERSION %lu, %lu, %lu, %lu\n",
2157	     (f->product_version_ms >> 16) & 0xffff,
2158	     f->product_version_ms & 0xffff,
2159	     (f->product_version_ls >> 16) & 0xffff,
2160	     f->product_version_ls & 0xffff);
2161  if (f->file_flags_mask != 0)
2162    fprintf (e, " FILEFLAGSMASK 0x%lx\n", f->file_flags_mask);
2163  if (f->file_flags != 0)
2164    fprintf (e, " FILEFLAGS 0x%lx\n", f->file_flags);
2165  if (f->file_os != 0)
2166    fprintf (e, " FILEOS 0x%lx\n", f->file_os);
2167  if (f->file_type != 0)
2168    fprintf (e, " FILETYPE 0x%lx\n", f->file_type);
2169  if (f->file_subtype != 0)
2170    fprintf (e, " FILESUBTYPE 0x%lx\n", f->file_subtype);
2171  if (f->file_date_ms != 0 || f->file_date_ls != 0)
2172    fprintf (e, "// Date: %lu, %lu\n", f->file_date_ms, f->file_date_ls);
2173
2174  fprintf (e, "BEGIN\n");
2175
2176  for (vi = versioninfo->var; vi != NULL; vi = vi->next)
2177    {
2178      switch (vi->type)
2179	{
2180	case VERINFO_STRING:
2181	  {
2182	    const struct ver_stringinfo *vs;
2183
2184	    fprintf (e, "  BLOCK \"StringFileInfo\"\n");
2185	    fprintf (e, "  BEGIN\n");
2186	    fprintf (e, "    BLOCK \"");
2187	    unicode_print (e, vi->u.string.language, -1);
2188	    fprintf (e, "\"\n");
2189	    fprintf (e, "    BEGIN\n");
2190
2191	    for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
2192	      {
2193		fprintf (e, "      VALUE \"");
2194		unicode_print (e, vs->key, -1);
2195		fprintf (e, "\", \"");
2196		unicode_print (e, vs->value, -1);
2197		fprintf (e, "\"\n");
2198	      }
2199
2200	    fprintf (e, "    END\n");
2201	    fprintf (e, "  END\n");
2202	    break;
2203	  }
2204
2205	case VERINFO_VAR:
2206	  {
2207	    const struct ver_varinfo *vv;
2208
2209	    fprintf (e, "  BLOCK \"VarFileInfo\"\n");
2210	    fprintf (e, "  BEGIN\n");
2211	    fprintf (e, "    VALUE \"");
2212	    unicode_print (e, vi->u.var.key, -1);
2213	    fprintf (e, "\"");
2214
2215	    for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
2216	      fprintf (e, ", 0x%x, %d", (unsigned int) vv->language,
2217		       vv->charset);
2218
2219	    fprintf (e, "\n  END\n");
2220
2221	    break;
2222	  }
2223	}
2224    }
2225
2226  fprintf (e, "END\n");
2227}
2228
2229/* Write out data which would normally be read from a file.  */
2230
2231static void
2232write_rc_filedata (e, length, data)
2233     FILE *e;
2234     unsigned long length;
2235     const unsigned char *data;
2236{
2237  unsigned long i;
2238
2239  for (i = 0; i + 15 < length; i += 16)
2240    {
2241      fprintf (e, "// %4lx: ", i);
2242      fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x ",
2243	       data[i + 0], data[i + 1], data[i + 2], data[i + 3],
2244	       data[i + 4], data[i + 5], data[i + 6], data[i + 7]);
2245      fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
2246	       data[i +  8], data[i +  9], data[i + 10], data[i + 11],
2247	       data[i + 12], data[i + 13], data[i + 14], data[i + 15]);
2248    }
2249
2250  if (i < length)
2251    {
2252      fprintf (e, "// %4lx:", i);
2253      while (i < length)
2254	{
2255	  fprintf (e, " %02x", data[i]);
2256	  ++i;
2257	}
2258      fprintf (e, "\n");
2259    }
2260}
2261