1 /* resrc.c -- read and write Windows rc files.
2 Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007
3 Free Software Foundation, Inc.
4 Written by Ian Lance Taylor, Cygnus Support.
5 Rewritten by Kai Tietz, Onevision.
7 This file is part of GNU Binutils.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
24 /* This file contains functions that read and write Windows rc files.
25 These are text files that represent resources. */
30 #include "libiberty.h"
31 #include "safe-ctype.h"
41 #ifdef HAVE_SYS_WAIT_H
43 #else /* ! HAVE_SYS_WAIT_H */
44 #if ! defined (_WIN32) || defined (__CYGWIN__)
46 #define WIFEXITED(w) (((w)&0377) == 0)
49 #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
52 #define WTERMSIG(w) ((w) & 0177)
55 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
57 #else /* defined (_WIN32) && ! defined (__CYGWIN__) */
59 #define WIFEXITED(w) (((w) & 0xff) == 0)
62 #define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
65 #define WTERMSIG(w) ((w) & 0x7f)
68 #define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
70 #endif /* defined (_WIN32) && ! defined (__CYGWIN__) */
71 #endif /* ! HAVE_SYS_WAIT_H */
74 #define STDOUT_FILENO 1
77 #if defined (_WIN32) && ! defined (__CYGWIN__)
79 #define pclose _pclose
82 /* The default preprocessor. */
84 #define DEFAULT_PREPROCESSOR "gcc -E -xc -DRC_INVOKED"
86 /* We read the directory entries in a cursor or icon file into
87 instances of this structure. */
93 /* Height of image. */
95 /* Number of colors in image. */
102 unsigned short planes
;
103 /* Bits per pixel. */
108 /* X coordinate of hotspot. */
109 unsigned short xhotspot
;
110 /* Y coordinate of hotspot. */
111 unsigned short yhotspot
;
114 /* Bytes in image. */
116 /* File offset of image. */
117 unsigned long offset
;
120 /* The name of the rc file we are reading. */
124 /* The line number in the rc file. */
128 /* The pipe we are reading from, so that we can close it if we exit. */
132 /* The temporary file used if we're not using popen, so we can delete it
135 static char *cpp_temp_file
;
137 /* Input stream is either a file or a pipe. */
139 static enum {ISTREAM_PIPE
, ISTREAM_FILE
} istream_type
;
141 /* As we read the rc file, we attach information to this structure. */
143 static rc_res_directory
*resources
;
145 /* The number of cursor resources we have written out. */
149 /* The number of font resources we have written out. */
153 /* Font directory information. */
155 rc_fontdir
*fontdirs
;
157 /* Resource info to use for fontdirs. */
159 rc_res_res_info fontdirs_resinfo
;
161 /* The number of icon resources we have written out. */
165 /* The windres target bfd . */
167 static windres_bfd wrtarget
=
169 (bfd
*) NULL
, (asection
*) NULL
, WR_KIND_TARGET
172 /* Local functions for rcdata based resource definitions. */
174 static void define_font_rcdata (rc_res_id
, const rc_res_res_info
*,
176 static void define_icon_rcdata (rc_res_id
, const rc_res_res_info
*,
178 static void define_bitmap_rcdata (rc_res_id
, const rc_res_res_info
*,
180 static void define_cursor_rcdata (rc_res_id
, const rc_res_res_info
*,
182 static void define_fontdir_rcdata (rc_res_id
, const rc_res_res_info
*,
184 static void define_messagetable_rcdata (rc_res_id
, const rc_res_res_info
*,
186 static rc_uint_type
rcdata_copy (const rc_rcdata_item
*, bfd_byte
*);
187 static bfd_byte
*rcdata_render_as_buffer (const rc_rcdata_item
*, rc_uint_type
*);
189 static int run_cmd (char *, const char *);
190 static FILE *open_input_stream (char *);
191 static FILE *look_for_default
192 (char *, const char *, int, const char *, const char *);
193 static void close_input_stream (void);
194 static void unexpected_eof (const char *);
195 static int get_word (FILE *, const char *);
196 static unsigned long get_long (FILE *, const char *);
197 static void get_data (FILE *, bfd_byte
*, rc_uint_type
, const char *);
198 static void define_fontdirs (void);
200 /* Run `cmd' and redirect the output to `redir'. */
203 run_cmd (char *cmd
, const char *redir
)
206 int pid
, wait_status
, retcode
;
209 char *errmsg_fmt
, *errmsg_arg
;
210 char *temp_base
= choose_temp_base ();
213 int redir_handle
= -1;
214 int stdout_save
= -1;
216 /* Count the args. */
219 for (s
= cmd
; *s
; s
++)
224 argv
= alloca (sizeof (char *) * (i
+ 3));
230 while (*s
== ' ' && *s
!= 0)
236 in_quote
= (*s
== '\'' || *s
== '"');
237 sep
= (in_quote
) ? *s
++ : ' ';
240 while (*s
!= sep
&& *s
!= 0)
253 /* Setup the redirection. We can't use the usual fork/exec and redirect
254 since we may be running on non-POSIX Windows host. */
259 /* Open temporary output file. */
260 redir_handle
= open (redir
, O_WRONLY
| O_TRUNC
| O_CREAT
, 0666);
261 if (redir_handle
== -1)
262 fatal (_("can't open temporary file `%s': %s"), redir
,
265 /* Duplicate the stdout file handle so it can be restored later. */
266 stdout_save
= dup (STDOUT_FILENO
);
267 if (stdout_save
== -1)
268 fatal (_("can't redirect stdout: `%s': %s"), redir
, strerror (errno
));
270 /* Redirect stdout to our output file. */
271 dup2 (redir_handle
, STDOUT_FILENO
);
273 pid
= pexecute (argv
[0], (char * const *) argv
, program_name
, temp_base
,
274 &errmsg_fmt
, &errmsg_arg
, PEXECUTE_ONE
| PEXECUTE_SEARCH
);
276 /* Restore stdout to its previous setting. */
277 dup2 (stdout_save
, STDOUT_FILENO
);
279 /* Close response file. */
280 close (redir_handle
);
284 fatal (_("%s %s: %s"), errmsg_fmt
, errmsg_arg
, strerror (errno
));
289 pid
= pwait (pid
, &wait_status
, 0);
293 fatal (_("wait: %s"), strerror (errno
));
296 else if (WIFSIGNALED (wait_status
))
298 fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status
));
301 else if (WIFEXITED (wait_status
))
303 if (WEXITSTATUS (wait_status
) != 0)
305 fatal (_("%s exited with status %d"), cmd
,
306 WEXITSTATUS (wait_status
));
317 open_input_stream (char *cmd
)
319 if (istream_type
== ISTREAM_FILE
)
323 fileprefix
= choose_temp_base ();
324 cpp_temp_file
= (char *) xmalloc (strlen (fileprefix
) + 5);
325 sprintf (cpp_temp_file
, "%s.irc", fileprefix
);
328 if (run_cmd (cmd
, cpp_temp_file
))
329 fatal (_("can't execute `%s': %s"), cmd
, strerror (errno
));
331 cpp_pipe
= fopen (cpp_temp_file
, FOPEN_RT
);;
332 if (cpp_pipe
== NULL
)
333 fatal (_("can't open temporary file `%s': %s"),
334 cpp_temp_file
, strerror (errno
));
338 _("Using temporary file `%s' to read preprocessor output\n"),
343 cpp_pipe
= popen (cmd
, FOPEN_RT
);
344 if (cpp_pipe
== NULL
)
345 fatal (_("can't popen `%s': %s"), cmd
, strerror (errno
));
347 fprintf (stderr
, _("Using popen to read preprocessor output\n"));
350 xatexit (close_input_stream
);
354 /* look for the preprocessor program */
357 look_for_default (char *cmd
, const char *prefix
, int end_prefix
,
358 const char *preprocargs
, const char *filename
)
364 strcpy (cmd
, prefix
);
366 sprintf (cmd
+ end_prefix
, "%s", DEFAULT_PREPROCESSOR
);
367 space
= strchr (cmd
+ end_prefix
, ' ');
372 #if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32)
373 strchr (cmd
, '\\') ||
377 found
= (stat (cmd
, &s
) == 0
378 #ifdef HAVE_EXECUTABLE_SUFFIX
379 || stat (strcat (cmd
, EXECUTABLE_SUFFIX
), &s
) == 0
386 fprintf (stderr
, _("Tried `%s'\n"), cmd
);
391 strcpy (cmd
, prefix
);
393 sprintf (cmd
+ end_prefix
, "%s %s %s",
394 DEFAULT_PREPROCESSOR
, preprocargs
, filename
);
397 fprintf (stderr
, _("Using `%s'\n"), cmd
);
399 cpp_pipe
= open_input_stream (cmd
);
403 /* Read an rc file. */
406 read_rc_file (const char *filename
, const char *preprocessor
,
407 const char *preprocargs
, int language
, int use_temp_file
)
411 istream_type
= (use_temp_file
) ? ISTREAM_FILE
: ISTREAM_PIPE
;
413 if (preprocargs
== NULL
)
415 if (filename
== NULL
)
420 cmd
= xmalloc (strlen (preprocessor
)
421 + strlen (preprocargs
)
424 sprintf (cmd
, "%s %s %s", preprocessor
, preprocargs
, filename
);
426 cpp_pipe
= open_input_stream (cmd
);
430 char *dash
, *slash
, *cp
;
432 preprocessor
= DEFAULT_PREPROCESSOR
;
434 cmd
= xmalloc (strlen (program_name
)
435 + strlen (preprocessor
)
436 + strlen (preprocargs
)
438 #ifdef HAVE_EXECUTABLE_SUFFIX
439 + strlen (EXECUTABLE_SUFFIX
)
445 for (cp
= program_name
; *cp
; cp
++)
450 #if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32)
451 *cp
== ':' || *cp
== '\\' ||
464 /* First, try looking for a prefixed gcc in the windres
465 directory, with the same prefix as windres */
467 cpp_pipe
= look_for_default (cmd
, program_name
, dash
- program_name
+ 1,
468 preprocargs
, filename
);
471 if (slash
&& ! cpp_pipe
)
473 /* Next, try looking for a gcc in the same directory as
476 cpp_pipe
= look_for_default (cmd
, program_name
, slash
- program_name
+ 1,
477 preprocargs
, filename
);
482 /* Sigh, try the default */
484 cpp_pipe
= look_for_default (cmd
, "", 0, preprocargs
, filename
);
491 rc_filename
= xstrdup (filename
);
494 rcparse_set_language (language
);
496 rcparse_discard_strings ();
498 close_input_stream ();
500 if (fontdirs
!= NULL
)
509 /* Close the input stream if it is open. */
512 close_input_stream (void)
514 if (istream_type
== ISTREAM_FILE
)
516 if (cpp_pipe
!= NULL
)
519 if (cpp_temp_file
!= NULL
)
521 int errno_save
= errno
;
523 unlink (cpp_temp_file
);
525 free (cpp_temp_file
);
530 if (cpp_pipe
!= NULL
)
534 /* Since this is also run via xatexit, safeguard. */
536 cpp_temp_file
= NULL
;
539 /* Report an error while reading an rc file. */
542 yyerror (const char *msg
)
544 fatal ("%s:%d: %s", rc_filename
, rc_lineno
, msg
);
547 /* Issue a warning while reading an rc file. */
550 rcparse_warning (const char *msg
)
552 fprintf (stderr
, _("%s:%d: %s\n"), rc_filename
, rc_lineno
, msg
);
555 /* Die if we get an unexpected end of file. */
558 unexpected_eof (const char *msg
)
560 fatal (_("%s: unexpected EOF"), msg
);
563 /* Read a 16 bit word from a file. The data is assumed to be little
567 get_word (FILE *e
, const char *msg
)
574 unexpected_eof (msg
);
575 return ((b2
& 0xff) << 8) | (b1
& 0xff);
578 /* Read a 32 bit word from a file. The data is assumed to be little
582 get_long (FILE *e
, const char *msg
)
591 unexpected_eof (msg
);
592 return (((((((b4
& 0xff) << 8)
598 /* Read data from a file. This is a wrapper to do error checking. */
601 get_data (FILE *e
, bfd_byte
*p
, rc_uint_type c
, const char *msg
)
603 rc_uint_type got
; // $$$d
605 got
= (rc_uint_type
) fread (p
, 1, c
, e
);
609 fatal (_("%s: read of %lu returned %lu"), msg
, (long) c
, (long) got
);
612 /* Define an accelerator resource. */
615 define_accelerator (rc_res_id id
, const rc_res_res_info
*resinfo
,
616 rc_accelerator
*data
)
620 r
= define_standard_resource (&resources
, RT_ACCELERATOR
, id
,
621 resinfo
->language
, 0);
622 r
->type
= RES_TYPE_ACCELERATOR
;
624 r
->res_info
= *resinfo
;
627 /* Define a bitmap resource. Bitmap data is stored in a file. The
628 first 14 bytes of the file are a standard header, which is not
629 included in the resource data. */
631 #define BITMAP_SKIP (14)
634 define_bitmap (rc_res_id id
, const rc_res_res_info
*resinfo
,
635 const char *filename
)
644 e
= open_file_search (filename
, FOPEN_RB
, "bitmap file", &real_filename
);
646 if (stat (real_filename
, &s
) < 0)
647 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
650 data
= (bfd_byte
*) res_alloc (s
.st_size
- BITMAP_SKIP
);
652 for (i
= 0; i
< BITMAP_SKIP
; i
++)
655 get_data (e
, data
, s
.st_size
- BITMAP_SKIP
, real_filename
);
658 free (real_filename
);
660 r
= define_standard_resource (&resources
, RT_BITMAP
, id
,
661 resinfo
->language
, 0);
663 r
->type
= RES_TYPE_BITMAP
;
664 r
->u
.data
.length
= s
.st_size
- BITMAP_SKIP
;
665 r
->u
.data
.data
= data
;
666 r
->res_info
= *resinfo
;
669 /* Define a cursor resource. A cursor file may contain a set of
670 bitmaps, each representing the same cursor at various different
671 resolutions. They each get written out with a different ID. The
672 real cursor resource is then a group resource which can be used to
673 select one of the actual cursors. */
676 define_cursor (rc_res_id id
, const rc_res_res_info
*resinfo
,
677 const char *filename
)
682 struct icondir
*icondirs
;
685 rc_group_cursor
*first
, **pp
;
687 e
= open_file_search (filename
, FOPEN_RB
, "cursor file", &real_filename
);
689 /* A cursor file is basically an icon file. The start of the file
690 is a three word structure. The first word is ignored. The
691 second word is the type of data. The third word is the number of
694 get_word (e
, real_filename
);
695 type
= get_word (e
, real_filename
);
696 count
= get_word (e
, real_filename
);
698 fatal (_("cursor file `%s' does not contain cursor data"), real_filename
);
700 /* Read in the icon directory entries. */
702 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
704 for (i
= 0; i
< count
; i
++)
706 icondirs
[i
].width
= getc (e
);
707 icondirs
[i
].height
= getc (e
);
708 icondirs
[i
].colorcount
= getc (e
);
710 icondirs
[i
].u
.cursor
.xhotspot
= get_word (e
, real_filename
);
711 icondirs
[i
].u
.cursor
.yhotspot
= get_word (e
, real_filename
);
712 icondirs
[i
].bytes
= get_long (e
, real_filename
);
713 icondirs
[i
].offset
= get_long (e
, real_filename
);
716 unexpected_eof (real_filename
);
719 /* Define each cursor as a unique resource. */
721 first_cursor
= cursors
;
723 for (i
= 0; i
< count
; i
++)
729 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
730 fatal (_("%s: fseek to %lu failed: %s"), real_filename
,
731 icondirs
[i
].offset
, strerror (errno
));
733 data
= (bfd_byte
*) res_alloc (icondirs
[i
].bytes
);
735 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
737 c
= (rc_cursor
*) res_alloc (sizeof (rc_cursor
));
738 c
->xhotspot
= icondirs
[i
].u
.cursor
.xhotspot
;
739 c
->yhotspot
= icondirs
[i
].u
.cursor
.yhotspot
;
740 c
->length
= icondirs
[i
].bytes
;
748 r
= define_standard_resource (&resources
, RT_CURSOR
, name
,
749 resinfo
->language
, 0);
750 r
->type
= RES_TYPE_CURSOR
;
752 r
->res_info
= *resinfo
;
756 free (real_filename
);
758 /* Define a cursor group resource. */
762 for (i
= 0; i
< count
; i
++)
766 cg
= (rc_group_cursor
*) res_alloc (sizeof (rc_group_cursor
));
768 cg
->width
= icondirs
[i
].width
;
769 cg
->height
= 2 * icondirs
[i
].height
;
771 /* FIXME: What should these be set to? */
775 cg
->bytes
= icondirs
[i
].bytes
+ 4;
776 cg
->index
= first_cursor
+ i
+ 1;
784 r
= define_standard_resource (&resources
, RT_GROUP_CURSOR
, id
,
785 resinfo
->language
, 0);
786 r
->type
= RES_TYPE_GROUP_CURSOR
;
787 r
->u
.group_cursor
= first
;
788 r
->res_info
= *resinfo
;
791 /* Define a dialog resource. */
794 define_dialog (rc_res_id id
, const rc_res_res_info
*resinfo
,
795 const rc_dialog
*dialog
)
800 copy
= (rc_dialog
*) res_alloc (sizeof *copy
);
803 r
= define_standard_resource (&resources
, RT_DIALOG
, id
,
804 resinfo
->language
, 0);
805 r
->type
= RES_TYPE_DIALOG
;
807 r
->res_info
= *resinfo
;
810 /* Define a dialog control. This does not define a resource, but
811 merely allocates and fills in a structure. */
814 define_control (const rc_res_id iid
, rc_uint_type id
, rc_uint_type x
,
815 rc_uint_type y
, rc_uint_type width
, rc_uint_type height
,
816 const rc_res_id
class, rc_uint_type style
,
817 rc_uint_type exstyle
)
819 rc_dialog_control
*n
;
821 n
= (rc_dialog_control
*) res_alloc (sizeof (rc_dialog_control
));
825 n
->exstyle
= exstyle
;
839 define_icon_control (rc_res_id iid
, rc_uint_type id
, rc_uint_type x
,
840 rc_uint_type y
, rc_uint_type style
,
841 rc_uint_type exstyle
, rc_uint_type help
,
842 rc_rcdata_item
*data
, rc_dialog_ex
*ex
)
844 rc_dialog_control
*n
;
849 style
= SS_ICON
| WS_CHILD
| WS_VISIBLE
;
850 res_string_to_id (&tid
, "");
852 cid
.u
.id
= CTL_STATIC
;
853 n
= define_control (tid
, id
, x
, y
, 0, 0, cid
, style
, exstyle
);
856 rcparse_warning (_("help ID requires DIALOGEX"));
858 rcparse_warning (_("control data requires DIALOGEX"));
865 /* Define a font resource. */
868 define_font (rc_res_id id
, const rc_res_res_info
*resinfo
,
869 const char *filename
)
880 const char *device
, *face
;
883 e
= open_file_search (filename
, FOPEN_RB
, "font file", &real_filename
);
885 if (stat (real_filename
, &s
) < 0)
886 fatal (_("stat failed on font file `%s': %s"), real_filename
,
889 data
= (bfd_byte
*) res_alloc (s
.st_size
);
891 get_data (e
, data
, s
.st_size
, real_filename
);
894 free (real_filename
);
896 r
= define_standard_resource (&resources
, RT_FONT
, id
,
897 resinfo
->language
, 0);
899 r
->type
= RES_TYPE_FONT
;
900 r
->u
.data
.length
= s
.st_size
;
901 r
->u
.data
.data
= data
;
902 r
->res_info
= *resinfo
;
904 /* For each font resource, we must add an entry in the FONTDIR
905 resource. The FONTDIR resource includes some strings in the font
906 file. To find them, we have to do some magic on the data we have
909 offset
= ((((((data
[47] << 8)
913 if (offset
> 0 && offset
< s
.st_size
)
914 device
= (char *) data
+ offset
;
918 offset
= ((((((data
[51] << 8)
922 if (offset
> 0 && offset
< s
.st_size
)
923 face
= (char *) data
+ offset
;
929 fontdatalength
= 58 + strlen (device
) + strlen (face
);
930 fontdata
= (bfd_byte
*) res_alloc (fontdatalength
);
931 memcpy (fontdata
, data
, 56);
932 strcpy ((char *) fontdata
+ 56, device
);
933 strcpy ((char *) fontdata
+ 57 + strlen (device
), face
);
935 fd
= (rc_fontdir
*) res_alloc (sizeof (rc_fontdir
));
938 fd
->length
= fontdatalength
;
941 for (pp
= &fontdirs
; *pp
!= NULL
; pp
= &(*pp
)->next
)
945 /* For the single fontdirs resource, we always use the resource
946 information of the last font. I don't know what else to do. */
947 fontdirs_resinfo
= *resinfo
;
951 define_font_rcdata (rc_res_id id
,const rc_res_res_info
*resinfo
,
952 rc_rcdata_item
*data
)
955 rc_uint_type len_data
;
958 r
= define_standard_resource (&resources
, RT_FONT
, id
,
959 resinfo
->language
, 0);
961 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
963 r
->type
= RES_TYPE_FONT
;
964 r
->u
.data
.length
= len_data
;
965 r
->u
.data
.data
= pb_data
;
966 r
->res_info
= *resinfo
;
969 /* Define the fontdirs resource. This is called after the entire rc
970 file has been parsed, if any font resources were seen. */
973 define_fontdirs (void)
981 r
= define_standard_resource (&resources
, RT_FONTDIR
, id
, 0x409, 0);
983 r
->type
= RES_TYPE_FONTDIR
;
984 r
->u
.fontdir
= fontdirs
;
985 r
->res_info
= fontdirs_resinfo
;
989 rcdata_render_as_buffer (const rc_rcdata_item
*data
, rc_uint_type
*plen
)
991 const rc_rcdata_item
*d
;
992 bfd_byte
*ret
= NULL
, *pret
;
993 rc_uint_type len
= 0;
995 for (d
= data
; d
!= NULL
; d
= d
->next
)
996 len
+= rcdata_copy (d
, NULL
);
999 ret
= pret
= (bfd_byte
*) res_alloc (len
);
1000 for (d
= data
; d
!= NULL
; d
= d
->next
)
1001 pret
+= rcdata_copy (d
, pret
);
1009 define_fontdir_rcdata (rc_res_id id
,const rc_res_res_info
*resinfo
,
1010 rc_rcdata_item
*data
)
1013 rc_fontdir
*fd
, *fd_first
, *fd_cur
;
1014 rc_uint_type len_data
;
1018 fd_cur
= fd_first
= NULL
;
1019 r
= define_standard_resource (&resources
, RT_FONTDIR
, id
, 0x409, 0);
1021 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
1025 rc_uint_type off
= 2;
1026 c
= windres_get_16 (&wrtarget
, pb_data
, len_data
);
1030 rc_uint_type safe_pos
= off
;
1031 const struct bin_fontdir_item
*bfi
;
1033 bfi
= (const struct bin_fontdir_item
*) pb_data
+ off
;
1034 fd
= (rc_fontdir
*) res_alloc (sizeof (rc_fontdir
));
1035 fd
->index
= windres_get_16 (&wrtarget
, bfi
->index
, len_data
- off
);
1036 fd
->data
= pb_data
+ off
;
1038 len
= strlen ((char *) bfi
->device_name
) + 1;
1039 off
+= (rc_uint_type
) len
;
1040 off
+= (rc_uint_type
) strlen ((char *) bfi
->device_name
+ len
) + 1;
1041 fd
->length
= (off
- safe_pos
);
1043 if (fd_first
== NULL
)
1050 r
->type
= RES_TYPE_FONTDIR
;
1051 r
->u
.fontdir
= fd_first
;
1052 r
->res_info
= *resinfo
;
1055 static void define_messagetable_rcdata (rc_res_id id
, const rc_res_res_info
*resinfo
,
1056 rc_rcdata_item
*data
)
1059 rc_uint_type len_data
;
1062 r
= define_standard_resource (&resources
, RT_MESSAGETABLE
, id
, resinfo
->language
, 0);
1064 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
1065 r
->type
= RES_TYPE_MESSAGETABLE
;
1066 r
->u
.data
.length
= len_data
;
1067 r
->u
.data
.data
= pb_data
;
1068 r
->res_info
= *resinfo
;
1071 /* Define an icon resource. An icon file may contain a set of
1072 bitmaps, each representing the same icon at various different
1073 resolutions. They each get written out with a different ID. The
1074 real icon resource is then a group resource which can be used to
1075 select one of the actual icon bitmaps. */
1078 define_icon (rc_res_id id
, const rc_res_res_info
*resinfo
,
1079 const char *filename
)
1082 char *real_filename
;
1084 struct icondir
*icondirs
;
1087 rc_group_icon
*first
, **pp
;
1089 e
= open_file_search (filename
, FOPEN_RB
, "icon file", &real_filename
);
1091 /* The start of an icon file is a three word structure. The first
1092 word is ignored. The second word is the type of data. The third
1093 word is the number of entries. */
1095 get_word (e
, real_filename
);
1096 type
= get_word (e
, real_filename
);
1097 count
= get_word (e
, real_filename
);
1099 fatal (_("icon file `%s' does not contain icon data"), real_filename
);
1101 /* Read in the icon directory entries. */
1103 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
1105 for (i
= 0; i
< count
; i
++)
1107 icondirs
[i
].width
= getc (e
);
1108 icondirs
[i
].height
= getc (e
);
1109 icondirs
[i
].colorcount
= getc (e
);
1111 icondirs
[i
].u
.icon
.planes
= get_word (e
, real_filename
);
1112 icondirs
[i
].u
.icon
.bits
= get_word (e
, real_filename
);
1113 icondirs
[i
].bytes
= get_long (e
, real_filename
);
1114 icondirs
[i
].offset
= get_long (e
, real_filename
);
1117 unexpected_eof (real_filename
);
1120 /* Define each icon as a unique resource. */
1124 for (i
= 0; i
< count
; i
++)
1129 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
1130 fatal (_("%s: fseek to %lu failed: %s"), real_filename
,
1131 icondirs
[i
].offset
, strerror (errno
));
1133 data
= (bfd_byte
*) res_alloc (icondirs
[i
].bytes
);
1135 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
1142 r
= define_standard_resource (&resources
, RT_ICON
, name
,
1143 resinfo
->language
, 0);
1144 r
->type
= RES_TYPE_ICON
;
1145 r
->u
.data
.length
= icondirs
[i
].bytes
;
1146 r
->u
.data
.data
= data
;
1147 r
->res_info
= *resinfo
;
1151 free (real_filename
);
1153 /* Define an icon group resource. */
1157 for (i
= 0; i
< count
; i
++)
1161 /* For some reason, at least in some files the planes and bits
1162 are zero. We instead set them from the color. This is
1165 cg
= (rc_group_icon
*) res_alloc (sizeof (rc_group_icon
));
1167 cg
->width
= icondirs
[i
].width
;
1168 cg
->height
= icondirs
[i
].height
;
1169 cg
->colors
= icondirs
[i
].colorcount
;
1171 if (icondirs
[i
].u
.icon
.planes
)
1172 cg
->planes
= icondirs
[i
].u
.icon
.planes
;
1176 if (icondirs
[i
].u
.icon
.bits
)
1177 cg
->bits
= icondirs
[i
].u
.icon
.bits
;
1182 while ((1L << cg
->bits
) < cg
->colors
)
1186 cg
->bytes
= icondirs
[i
].bytes
;
1187 cg
->index
= first_icon
+ i
+ 1;
1195 r
= define_standard_resource (&resources
, RT_GROUP_ICON
, id
,
1196 resinfo
->language
, 0);
1197 r
->type
= RES_TYPE_GROUP_ICON
;
1198 r
->u
.group_icon
= first
;
1199 r
->res_info
= *resinfo
;
1203 define_group_icon_rcdata (rc_res_id id
, const rc_res_res_info
*resinfo
,
1204 rc_rcdata_item
*data
)
1207 rc_group_icon
*cg
, *first
, *cur
;
1208 rc_uint_type len_data
;
1211 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
1216 while (len_data
>= 6)
1219 unsigned short type
;
1220 type
= windres_get_16 (&wrtarget
, pb_data
+ 2, len_data
- 2);
1222 fatal (_("unexpected group icon type %d"), type
);
1223 c
= windres_get_16 (&wrtarget
, pb_data
+ 4, len_data
- 4);
1227 for (i
= 0; i
< c
; i
++)
1230 fatal ("too small group icon rcdata");
1231 cg
= (rc_group_icon
*) res_alloc (sizeof (rc_group_icon
));
1233 cg
->width
= pb_data
[0];
1234 cg
->height
= pb_data
[1];
1235 cg
->colors
= pb_data
[2];
1236 cg
->planes
= windres_get_16 (&wrtarget
, pb_data
+ 4, len_data
- 4);
1237 cg
->bits
= windres_get_16 (&wrtarget
, pb_data
+ 6, len_data
- 6);
1238 cg
->bytes
= windres_get_32 (&wrtarget
, pb_data
+ 8, len_data
- 8);
1239 cg
->index
= windres_get_16 (&wrtarget
, pb_data
+ 12, len_data
- 12);
1249 r
= define_standard_resource (&resources
, RT_GROUP_ICON
, id
,
1250 resinfo
->language
, 0);
1251 r
->type
= RES_TYPE_GROUP_ICON
;
1252 r
->u
.group_icon
= first
;
1253 r
->res_info
= *resinfo
;
1257 define_group_cursor_rcdata (rc_res_id id
, const rc_res_res_info
*resinfo
,
1258 rc_rcdata_item
*data
)
1261 rc_group_cursor
*cg
, *first
, *cur
;
1262 rc_uint_type len_data
;
1265 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
1269 while (len_data
>= 6)
1272 unsigned short type
;
1273 type
= windres_get_16 (&wrtarget
, pb_data
+ 2, len_data
- 2);
1275 fatal (_("unexpected group cursor type %d"), type
);
1276 c
= windres_get_16 (&wrtarget
, pb_data
+ 4, len_data
- 4);
1280 for (i
= 0; i
< c
; i
++)
1283 fatal ("too small group icon rcdata");
1284 cg
= (rc_group_cursor
*) res_alloc (sizeof (rc_group_cursor
));
1286 cg
->width
= windres_get_16 (&wrtarget
, pb_data
, len_data
);
1287 cg
->height
= windres_get_16 (&wrtarget
, pb_data
+ 2, len_data
- 2);
1288 cg
->planes
= windres_get_16 (&wrtarget
, pb_data
+ 4, len_data
- 4);
1289 cg
->bits
= windres_get_16 (&wrtarget
, pb_data
+ 6, len_data
- 6);
1290 cg
->bytes
= windres_get_32 (&wrtarget
, pb_data
+ 8, len_data
- 8);
1291 cg
->index
= windres_get_16 (&wrtarget
, pb_data
+ 12, len_data
- 12);
1302 r
= define_standard_resource (&resources
, RT_GROUP_ICON
, id
,
1303 resinfo
->language
, 0);
1304 r
->type
= RES_TYPE_GROUP_CURSOR
;
1305 r
->u
.group_cursor
= first
;
1306 r
->res_info
= *resinfo
;
1310 define_cursor_rcdata (rc_res_id id
, const rc_res_res_info
*resinfo
,
1311 rc_rcdata_item
*data
)
1315 rc_uint_type len_data
;
1318 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
1320 c
= (rc_cursor
*) res_alloc (sizeof (rc_cursor
));
1321 c
->xhotspot
= windres_get_16 (&wrtarget
, pb_data
, len_data
);
1322 c
->yhotspot
= windres_get_16 (&wrtarget
, pb_data
+ 2, len_data
- 2);
1323 c
->length
= len_data
- BIN_CURSOR_SIZE
;
1324 c
->data
= (const bfd_byte
*) (data
+ BIN_CURSOR_SIZE
);
1326 r
= define_standard_resource (&resources
, RT_CURSOR
, id
, resinfo
->language
, 0);
1327 r
->type
= RES_TYPE_CURSOR
;
1329 r
->res_info
= *resinfo
;
1333 define_bitmap_rcdata (rc_res_id id
, const rc_res_res_info
*resinfo
,
1334 rc_rcdata_item
*data
)
1337 rc_uint_type len_data
;
1340 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
1342 r
= define_standard_resource (&resources
, RT_BITMAP
, id
, resinfo
->language
, 0);
1343 r
->type
= RES_TYPE_BITMAP
;
1344 r
->u
.data
.length
= len_data
;
1345 r
->u
.data
.data
= pb_data
;
1346 r
->res_info
= *resinfo
;
1350 define_icon_rcdata (rc_res_id id
, const rc_res_res_info
*resinfo
,
1351 rc_rcdata_item
*data
)
1354 rc_uint_type len_data
;
1357 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
1359 r
= define_standard_resource (&resources
, RT_ICON
, id
, resinfo
->language
, 0);
1360 r
->type
= RES_TYPE_ICON
;
1361 r
->u
.data
.length
= len_data
;
1362 r
->u
.data
.data
= pb_data
;
1363 r
->res_info
= *resinfo
;
1366 /* Define a menu resource. */
1369 define_menu (rc_res_id id
, const rc_res_res_info
*resinfo
,
1370 rc_menuitem
*menuitems
)
1375 m
= (rc_menu
*) res_alloc (sizeof (rc_menu
));
1376 m
->items
= menuitems
;
1379 r
= define_standard_resource (&resources
, RT_MENU
, id
, resinfo
->language
, 0);
1380 r
->type
= RES_TYPE_MENU
;
1382 r
->res_info
= *resinfo
;
1385 /* Define a menu item. This does not define a resource, but merely
1386 allocates and fills in a structure. */
1389 define_menuitem (const unichar
*text
, rc_uint_type menuid
, rc_uint_type type
,
1390 rc_uint_type state
, rc_uint_type help
,
1391 rc_menuitem
*menuitems
)
1395 mi
= (rc_menuitem
*) res_alloc (sizeof (rc_menuitem
));
1400 mi
->text
= unichar_dup (text
);
1402 mi
->popup
= menuitems
;
1406 /* Define a messagetable resource. */
1409 define_messagetable (rc_res_id id
, const rc_res_res_info
*resinfo
,
1410 const char *filename
)
1413 char *real_filename
;
1418 e
= open_file_search (filename
, FOPEN_RB
, "messagetable file",
1421 if (stat (real_filename
, &s
) < 0)
1422 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
1425 data
= (bfd_byte
*) res_alloc (s
.st_size
);
1427 get_data (e
, data
, s
.st_size
, real_filename
);
1430 free (real_filename
);
1432 r
= define_standard_resource (&resources
, RT_MESSAGETABLE
, id
,
1433 resinfo
->language
, 0);
1435 r
->type
= RES_TYPE_MESSAGETABLE
;
1436 r
->u
.data
.length
= s
.st_size
;
1437 r
->u
.data
.data
= data
;
1438 r
->res_info
= *resinfo
;
1441 /* Define an rcdata resource. */
1444 define_rcdata (rc_res_id id
, const rc_res_res_info
*resinfo
,
1445 rc_rcdata_item
*data
)
1449 r
= define_standard_resource (&resources
, RT_RCDATA
, id
,
1450 resinfo
->language
, 0);
1451 r
->type
= RES_TYPE_RCDATA
;
1453 r
->res_info
= *resinfo
;
1456 /* Create an rcdata item holding a string. */
1459 define_rcdata_string (const char *string
, rc_uint_type len
)
1464 ri
= (rc_rcdata_item
*) res_alloc (sizeof (rc_rcdata_item
));
1466 ri
->type
= RCDATA_STRING
;
1467 ri
->u
.string
.length
= len
;
1468 s
= (char *) res_alloc (len
);
1469 memcpy (s
, string
, len
);
1475 /* Create an rcdata item holding a unicode string. */
1478 define_rcdata_unistring (const unichar
*string
, rc_uint_type len
)
1483 ri
= (rc_rcdata_item
*) res_alloc (sizeof (rc_rcdata_item
));
1485 ri
->type
= RCDATA_WSTRING
;
1486 ri
->u
.wstring
.length
= len
;
1487 s
= (unichar
*) res_alloc (len
* sizeof (unichar
));
1488 memcpy (s
, string
, len
* sizeof (unichar
));
1489 ri
->u
.wstring
.w
= s
;
1494 /* Create an rcdata item holding a number. */
1497 define_rcdata_number (rc_uint_type val
, int dword
)
1501 ri
= (rc_rcdata_item
*) res_alloc (sizeof (rc_rcdata_item
));
1503 ri
->type
= dword
? RCDATA_DWORD
: RCDATA_WORD
;
1509 /* Define a stringtable resource. This is called for each string
1510 which appears in a STRINGTABLE statement. */
1513 define_stringtable (const rc_res_res_info
*resinfo
,
1514 rc_uint_type stringid
, const unichar
*string
)
1520 id
.u
.id
= (stringid
>> 4) + 1;
1521 r
= define_standard_resource (&resources
, RT_STRING
, id
,
1522 resinfo
->language
, 1);
1524 if (r
->type
== RES_TYPE_UNINITIALIZED
)
1528 r
->type
= RES_TYPE_STRINGTABLE
;
1529 r
->u
.stringtable
= ((rc_stringtable
*)
1530 res_alloc (sizeof (rc_stringtable
)));
1531 for (i
= 0; i
< 16; i
++)
1533 r
->u
.stringtable
->strings
[i
].length
= 0;
1534 r
->u
.stringtable
->strings
[i
].string
= NULL
;
1537 r
->res_info
= *resinfo
;
1540 r
->u
.stringtable
->strings
[stringid
& 0xf].length
= unichar_len (string
);
1541 r
->u
.stringtable
->strings
[stringid
& 0xf].string
= unichar_dup (string
);
1545 define_toolbar (rc_res_id id
, rc_res_res_info
*resinfo
, rc_uint_type width
, rc_uint_type height
,
1546 rc_toolbar_item
*items
)
1551 t
= (rc_toolbar
*) res_alloc (sizeof (rc_toolbar
));
1552 t
->button_width
= width
;
1553 t
->button_height
= height
;
1556 while (items
!= NULL
)
1559 items
= items
->next
;
1561 r
= define_standard_resource (&resources
, RT_TOOLBAR
, id
, resinfo
->language
, 0);
1562 r
->type
= RES_TYPE_TOOLBAR
;
1564 r
->res_info
= *resinfo
;
1567 /* Define a user data resource where the data is in the rc file. */
1570 define_user_data (rc_res_id id
, rc_res_id type
,
1571 const rc_res_res_info
*resinfo
,
1572 rc_rcdata_item
*data
)
1577 rc_uint_type len_data
;
1579 /* We have to check if the binary data is parsed specially. */
1580 if (type
.named
== 0)
1585 define_fontdir_rcdata (id
, resinfo
, data
);
1588 define_font_rcdata (id
, resinfo
, data
);
1591 define_icon_rcdata (id
, resinfo
, data
);
1594 define_bitmap_rcdata (id
, resinfo
, data
);
1597 define_cursor_rcdata (id
, resinfo
, data
);
1600 define_group_icon_rcdata (id
, resinfo
, data
);
1602 case RT_GROUP_CURSOR
:
1603 define_group_cursor_rcdata (id
, resinfo
, data
);
1605 case RT_MESSAGETABLE
:
1606 define_messagetable_rcdata (id
, resinfo
, data
);
1609 /* Treat as normal user-data. */
1616 ids
[2].u
.id
= resinfo
->language
;
1618 r
= define_resource (& resources
, 3, ids
, 0);
1619 r
->type
= RES_TYPE_USERDATA
;
1620 r
->u
.userdata
= ((rc_rcdata_item
*)
1621 res_alloc (sizeof (rc_rcdata_item
)));
1622 r
->u
.userdata
->next
= NULL
;
1623 r
->u
.userdata
->type
= RCDATA_BUFFER
;
1624 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
1625 r
->u
.userdata
->u
.buffer
.length
= len_data
;
1626 r
->u
.userdata
->u
.buffer
.data
= pb_data
;
1627 r
->res_info
= *resinfo
;
1631 define_rcdata_file (rc_res_id id
, const rc_res_res_info
*resinfo
,
1632 const char *filename
)
1636 char *real_filename
;
1640 e
= open_file_search (filename
, FOPEN_RB
, "file", &real_filename
);
1643 if (stat (real_filename
, &s
) < 0)
1644 fatal (_("stat failed on file `%s': %s"), real_filename
,
1647 data
= (bfd_byte
*) res_alloc (s
.st_size
);
1649 get_data (e
, data
, s
.st_size
, real_filename
);
1652 free (real_filename
);
1654 ri
= (rc_rcdata_item
*) res_alloc (sizeof (rc_rcdata_item
));
1656 ri
->type
= RCDATA_BUFFER
;
1657 ri
->u
.buffer
.length
= s
.st_size
;
1658 ri
->u
.buffer
.data
= data
;
1660 define_rcdata (id
, resinfo
, ri
);
1663 /* Define a user data resource where the data is in a file. */
1666 define_user_file (rc_res_id id
, rc_res_id type
,
1667 const rc_res_res_info
*resinfo
, const char *filename
)
1670 char *real_filename
;
1676 e
= open_file_search (filename
, FOPEN_RB
, "file", &real_filename
);
1678 if (stat (real_filename
, &s
) < 0)
1679 fatal (_("stat failed on file `%s': %s"), real_filename
,
1682 data
= (bfd_byte
*) res_alloc (s
.st_size
);
1684 get_data (e
, data
, s
.st_size
, real_filename
);
1687 free (real_filename
);
1692 ids
[2].u
.id
= resinfo
->language
;
1694 r
= define_resource (&resources
, 3, ids
, 0);
1695 r
->type
= RES_TYPE_USERDATA
;
1696 r
->u
.userdata
= ((rc_rcdata_item
*)
1697 res_alloc (sizeof (rc_rcdata_item
)));
1698 r
->u
.userdata
->next
= NULL
;
1699 r
->u
.userdata
->type
= RCDATA_BUFFER
;
1700 r
->u
.userdata
->u
.buffer
.length
= s
.st_size
;
1701 r
->u
.userdata
->u
.buffer
.data
= data
;
1702 r
->res_info
= *resinfo
;
1705 /* Define a versioninfo resource. */
1708 define_versioninfo (rc_res_id id
, rc_uint_type language
,
1709 rc_fixed_versioninfo
*fixedverinfo
,
1710 rc_ver_info
*verinfo
)
1714 r
= define_standard_resource (&resources
, RT_VERSION
, id
, language
, 0);
1715 r
->type
= RES_TYPE_VERSIONINFO
;
1716 r
->u
.versioninfo
= ((rc_versioninfo
*)
1717 res_alloc (sizeof (rc_versioninfo
)));
1718 r
->u
.versioninfo
->fixed
= fixedverinfo
;
1719 r
->u
.versioninfo
->var
= verinfo
;
1720 r
->res_info
.language
= language
;
1723 /* Add string version info to a list of version information. */
1726 append_ver_stringfileinfo (rc_ver_info
*verinfo
, const char *language
,
1727 rc_ver_stringinfo
*strings
)
1729 rc_ver_info
*vi
, **pp
;
1731 vi
= (rc_ver_info
*) res_alloc (sizeof (rc_ver_info
));
1733 vi
->type
= VERINFO_STRING
;
1734 unicode_from_ascii ((rc_uint_type
*) NULL
, &vi
->u
.string
.language
, language
);
1735 vi
->u
.string
.strings
= strings
;
1737 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1744 /* Add variable version info to a list of version information. */
1747 append_ver_varfileinfo (rc_ver_info
*verinfo
, const unichar
*key
,
1748 rc_ver_varinfo
*var
)
1750 rc_ver_info
*vi
, **pp
;
1752 vi
= (rc_ver_info
*) res_alloc (sizeof *vi
);
1754 vi
->type
= VERINFO_VAR
;
1755 vi
->u
.var
.key
= unichar_dup (key
);
1756 vi
->u
.var
.var
= var
;
1758 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1765 /* Append version string information to a list. */
1768 append_verval (rc_ver_stringinfo
*strings
, const unichar
*key
,
1769 const unichar
*value
)
1771 rc_ver_stringinfo
*vs
, **pp
;
1773 vs
= (rc_ver_stringinfo
*) res_alloc (sizeof (rc_ver_stringinfo
));
1775 vs
->key
= unichar_dup (key
);
1776 vs
->value
= unichar_dup (value
);
1778 for (pp
= &strings
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1785 /* Append version variable information to a list. */
1788 append_vertrans (rc_ver_varinfo
*var
, rc_uint_type language
,
1789 rc_uint_type charset
)
1791 rc_ver_varinfo
*vv
, **pp
;
1793 vv
= (rc_ver_varinfo
*) res_alloc (sizeof (rc_ver_varinfo
));
1795 vv
->language
= language
;
1796 vv
->charset
= charset
;
1798 for (pp
= &var
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1805 /* Local functions used to write out an rc file. */
1807 static void indent (FILE *, int);
1808 static void write_rc_directory (FILE *, const rc_res_directory
*, const rc_res_id
*,
1809 const rc_res_id
*, rc_uint_type
*, int);
1810 static void write_rc_subdir (FILE *, const rc_res_entry
*, const rc_res_id
*,
1811 const rc_res_id
*, rc_uint_type
*, int);
1812 static void write_rc_resource (FILE *, const rc_res_id
*, const rc_res_id
*,
1813 const rc_res_resource
*, rc_uint_type
*);
1814 static void write_rc_accelerators (FILE *, const rc_accelerator
*);
1815 static void write_rc_cursor (FILE *, const rc_cursor
*);
1816 static void write_rc_group_cursor (FILE *, const rc_group_cursor
*);
1817 static void write_rc_dialog (FILE *, const rc_dialog
*);
1818 static void write_rc_dialog_control (FILE *, const rc_dialog_control
*);
1819 static void write_rc_fontdir (FILE *, const rc_fontdir
*);
1820 static void write_rc_group_icon (FILE *, const rc_group_icon
*);
1821 static void write_rc_menu (FILE *, const rc_menu
*, int);
1822 static void write_rc_toolbar (FILE *, const rc_toolbar
*);
1823 static void write_rc_menuitems (FILE *, const rc_menuitem
*, int, int);
1824 static void write_rc_messagetable (FILE *, rc_uint_type
, const bfd_byte
*);
1826 static void write_rc_datablock (FILE *, rc_uint_type
, const bfd_byte
*, int, int, int);
1827 static void write_rc_rcdata (FILE *, const rc_rcdata_item
*, int);
1828 static void write_rc_stringtable (FILE *, const rc_res_id
*, const rc_stringtable
*);
1829 static void write_rc_versioninfo (FILE *, const rc_versioninfo
*);
1831 /* Indent a given number of spaces. */
1834 indent (FILE *e
, int c
)
1838 for (i
= 0; i
< c
; i
++)
1842 /* Dump the resources we have read in the format of an rc file.
1844 Reasoned by the fact, that some resources need to be stored into file and
1845 refer to that file, we use the user-data model for that to express it binary
1846 without the need to store it somewhere externally. */
1849 write_rc_file (const char *filename
, const rc_res_directory
*resources
)
1852 rc_uint_type language
;
1854 if (filename
== NULL
)
1858 e
= fopen (filename
, FOPEN_WT
);
1860 fatal (_("can't open `%s' for output: %s"), filename
, strerror (errno
));
1863 language
= (rc_uint_type
) ((bfd_signed_vma
) -1);
1864 write_rc_directory (e
, resources
, (const rc_res_id
*) NULL
,
1865 (const rc_res_id
*) NULL
, &language
, 1);
1868 /* Write out a directory. E is the file to write to. RD is the
1869 directory. TYPE is a pointer to the level 1 ID which serves as the
1870 resource type. NAME is a pointer to the level 2 ID which serves as
1871 an individual resource name. LANGUAGE is a pointer to the current
1872 language. LEVEL is the level in the tree. */
1875 write_rc_directory (FILE *e
, const rc_res_directory
*rd
,
1876 const rc_res_id
*type
, const rc_res_id
*name
,
1877 rc_uint_type
*language
, int level
)
1879 const rc_res_entry
*re
;
1881 /* Print out some COFF information that rc files can't represent. */
1882 if (rd
->time
!= 0 || rd
->characteristics
!= 0 || rd
->major
!= 0 || rd
->minor
!= 0)
1884 wr_printcomment (e
, "COFF information not part of RC");
1886 wr_printcomment (e
, "Time stamp: %u", rd
->time
);
1887 if (rd
->characteristics
!= 0)
1888 wr_printcomment (e
, "Characteristics: %u", rd
->characteristics
);
1889 if (rd
->major
!= 0 || rd
->minor
!= 0)
1890 wr_printcomment (e
, "Version major:%d minor:%d", rd
->major
, rd
->minor
);
1893 for (re
= rd
->entries
; re
!= NULL
; re
= re
->next
)
1898 /* If we're at level 1, the key of this resource is the
1899 type. This normally duplicates the information we have
1900 stored with the resource itself, but we need to remember
1901 the type if this is a user define resource type. */
1906 /* If we're at level 2, the key of this resource is the name
1907 we are going to use in the rc printout. */
1912 /* If we're at level 3, then this key represents a language.
1913 Use it to update the current language. */
1915 && re
->id
.u
.id
!= (unsigned long) (unsigned int) *language
1916 && (re
->id
.u
.id
& 0xffff) == re
->id
.u
.id
)
1918 wr_print (e
, "LANGUAGE %u, %u\n",
1919 re
->id
.u
.id
& ((1 << SUBLANG_SHIFT
) - 1),
1920 (re
->id
.u
.id
>> SUBLANG_SHIFT
) & 0xff);
1921 *language
= re
->id
.u
.id
;
1930 write_rc_subdir (e
, re
, type
, name
, language
, level
);
1935 /* This is the normal case: the three levels are
1936 TYPE/NAME/LANGUAGE. NAME will have been set at level
1937 2, and represents the name to use. We probably just
1938 set LANGUAGE, and it will probably match what the
1939 resource itself records if anything. */
1940 write_rc_resource (e
, type
, name
, re
->u
.res
, language
);
1944 wr_printcomment (e
, "Resource at unexpected level %d", level
);
1945 write_rc_resource (e
, type
, (rc_res_id
*) NULL
, re
->u
.res
,
1950 if (rd
->entries
== NULL
)
1956 /* Write out a subdirectory entry. E is the file to write to. RE is
1957 the subdirectory entry. TYPE and NAME are pointers to higher level
1958 IDs, or NULL. LANGUAGE is a pointer to the current language.
1959 LEVEL is the level in the tree. */
1962 write_rc_subdir (FILE *e
, const rc_res_entry
*re
,
1963 const rc_res_id
*type
, const rc_res_id
*name
,
1964 rc_uint_type
*language
, int level
)
1970 wr_printcomment (e
, "Type: ");
1972 res_id_print (e
, re
->id
, 1);
1977 switch (re
->id
.u
.id
)
1979 case RT_CURSOR
: s
= "cursor"; break;
1980 case RT_BITMAP
: s
= "bitmap"; break;
1981 case RT_ICON
: s
= "icon"; break;
1982 case RT_MENU
: s
= "menu"; break;
1983 case RT_DIALOG
: s
= "dialog"; break;
1984 case RT_STRING
: s
= "stringtable"; break;
1985 case RT_FONTDIR
: s
= "fontdir"; break;
1986 case RT_FONT
: s
= "font"; break;
1987 case RT_ACCELERATOR
: s
= "accelerators"; break;
1988 case RT_RCDATA
: s
= "rcdata"; break;
1989 case RT_MESSAGETABLE
: s
= "messagetable"; break;
1990 case RT_GROUP_CURSOR
: s
= "group cursor"; break;
1991 case RT_GROUP_ICON
: s
= "group icon"; break;
1992 case RT_VERSION
: s
= "version"; break;
1993 case RT_DLGINCLUDE
: s
= "dlginclude"; break;
1994 case RT_PLUGPLAY
: s
= "plugplay"; break;
1995 case RT_VXD
: s
= "vxd"; break;
1996 case RT_ANICURSOR
: s
= "anicursor"; break;
1997 case RT_ANIICON
: s
= "aniicon"; break;
1998 case RT_TOOLBAR
: s
= "toolbar"; break;
1999 case RT_HTML
: s
= "html"; break;
2000 default: s
= NULL
; break;
2004 fprintf (e
, "%s", s
);
2006 res_id_print (e
, re
->id
, 1);
2011 wr_printcomment (e
, "Name: ");
2012 res_id_print (e
, re
->id
, 1);
2016 wr_printcomment (e
, "Language: ");
2017 res_id_print (e
, re
->id
, 1);
2021 wr_printcomment (e
, "Level %d: ", level
);
2022 res_id_print (e
, re
->id
, 1);
2025 write_rc_directory (e
, re
->u
.dir
, type
, name
, language
, level
+ 1);
2028 /* Write out a single resource. E is the file to write to. TYPE is a
2029 pointer to the type of the resource. NAME is a pointer to the name
2030 of the resource; it will be NULL if there is a level mismatch. RES
2031 is the resource data. LANGUAGE is a pointer to the current
2035 write_rc_resource (FILE *e
, const rc_res_id
*type
,
2036 const rc_res_id
*name
, const rc_res_resource
*res
,
2037 rc_uint_type
*language
)
2048 case RES_TYPE_ACCELERATOR
:
2050 rt
= RT_ACCELERATOR
;
2053 case RES_TYPE_BITMAP
:
2054 s
= "2 /* RT_BITMAP */";
2058 case RES_TYPE_CURSOR
:
2059 s
= "1 /* RT_CURSOR */";
2063 case RES_TYPE_GROUP_CURSOR
:
2064 s
= "12 /* RT_GROUP_CURSOR */";
2065 rt
= RT_GROUP_CURSOR
;
2068 case RES_TYPE_DIALOG
:
2069 if (extended_dialog (res
->u
.dialog
))
2077 s
= "8 /* RT_FONT */";
2081 case RES_TYPE_FONTDIR
:
2082 s
= "7 /* RT_FONTDIR */";
2087 s
= "3 /* RT_ICON */";
2091 case RES_TYPE_GROUP_ICON
:
2092 s
= "14 /* RT_GROUP_ICON */";
2097 if (extended_menu (res
->u
.menu
))
2110 case RES_TYPE_MESSAGETABLE
:
2111 s
= "11 /* RT_MESSAGETABLE */";
2112 rt
= RT_MESSAGETABLE
;
2115 case RES_TYPE_RCDATA
:
2120 case RES_TYPE_STRINGTABLE
:
2125 case RES_TYPE_USERDATA
:
2130 case RES_TYPE_VERSIONINFO
:
2135 case RES_TYPE_TOOLBAR
:
2143 && (type
->named
|| type
->u
.id
!= (unsigned long) rt
))
2145 wr_printcomment (e
, "Unexpected resource type mismatch: ");
2146 res_id_print (e
, *type
, 1);
2147 fprintf (e
, " != %d", rt
);
2150 if (res
->coff_info
.codepage
!= 0)
2151 wr_printcomment (e
, "Code page: %u", res
->coff_info
.codepage
);
2152 if (res
->coff_info
.reserved
!= 0)
2153 wr_printcomment (e
, "COFF reserved value: %u", res
->coff_info
.reserved
);
2156 if (rt
== RT_STRING
)
2161 res_id_print (e
, *name
, 1);
2163 fprintf (e
, "??Unknown-Name??");
2168 fprintf (e
, "%s", s
);
2169 else if (type
!= NULL
)
2171 if (type
->named
== 0)
2173 #define PRINT_RT_NAME(NAME) case NAME: \
2174 fprintf (e, "%u /* %s */", (unsigned int) NAME, #NAME); \
2180 res_id_print (e
, *type
, 0);
2183 PRINT_RT_NAME(RT_MANIFEST
);
2184 PRINT_RT_NAME(RT_ANICURSOR
);
2185 PRINT_RT_NAME(RT_ANIICON
);
2186 PRINT_RT_NAME(RT_RCDATA
);
2187 PRINT_RT_NAME(RT_ICON
);
2188 PRINT_RT_NAME(RT_CURSOR
);
2189 PRINT_RT_NAME(RT_BITMAP
);
2190 PRINT_RT_NAME(RT_PLUGPLAY
);
2191 PRINT_RT_NAME(RT_VXD
);
2192 PRINT_RT_NAME(RT_FONT
);
2193 PRINT_RT_NAME(RT_FONTDIR
);
2194 PRINT_RT_NAME(RT_HTML
);
2195 PRINT_RT_NAME(RT_MESSAGETABLE
);
2196 PRINT_RT_NAME(RT_DLGINCLUDE
);
2197 PRINT_RT_NAME(RT_DLGINIT
);
2199 #undef PRINT_RT_NAME
2202 res_id_print (e
, *type
, 1);
2205 fprintf (e
, "??Unknown-Type??");
2207 if (res
->res_info
.memflags
!= 0)
2209 if ((res
->res_info
.memflags
& MEMFLAG_MOVEABLE
) != 0)
2210 fprintf (e
, " MOVEABLE");
2211 if ((res
->res_info
.memflags
& MEMFLAG_PURE
) != 0)
2212 fprintf (e
, " PURE");
2213 if ((res
->res_info
.memflags
& MEMFLAG_PRELOAD
) != 0)
2214 fprintf (e
, " PRELOAD");
2215 if ((res
->res_info
.memflags
& MEMFLAG_DISCARDABLE
) != 0)
2216 fprintf (e
, " DISCARDABLE");
2219 if (res
->type
== RES_TYPE_DIALOG
)
2221 fprintf (e
, " %d, %d, %d, %d",
2222 (int) res
->u
.dialog
->x
, (int) res
->u
.dialog
->y
,
2223 (int) res
->u
.dialog
->width
, (int) res
->u
.dialog
->height
);
2224 if (res
->u
.dialog
->ex
!= NULL
2225 && res
->u
.dialog
->ex
->help
!= 0)
2226 fprintf (e
, ", %u", (unsigned int) res
->u
.dialog
->ex
->help
);
2228 else if (res
->type
== RES_TYPE_TOOLBAR
)
2230 fprintf (e
, " %d, %d", (int) res
->u
.toolbar
->button_width
,
2231 (int) res
->u
.toolbar
->button_height
);
2236 if ((res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
2237 || res
->res_info
.characteristics
!= 0
2238 || res
->res_info
.version
!= 0)
2244 case RES_TYPE_ACCELERATOR
:
2245 case RES_TYPE_DIALOG
:
2247 case RES_TYPE_RCDATA
:
2248 case RES_TYPE_STRINGTABLE
:
2257 if (res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
2258 fprintf (e
, "%sLANGUAGE %d, %d\n",
2259 modifiers
? "// " : "",
2260 (int) res
->res_info
.language
& ((1<<SUBLANG_SHIFT
)-1),
2261 (int) (res
->res_info
.language
>> SUBLANG_SHIFT
) & 0xff);
2262 if (res
->res_info
.characteristics
!= 0)
2263 fprintf (e
, "%sCHARACTERISTICS %u\n",
2264 modifiers
? "// " : "",
2265 (unsigned int) res
->res_info
.characteristics
);
2266 if (res
->res_info
.version
!= 0)
2267 fprintf (e
, "%sVERSION %u\n",
2268 modifiers
? "// " : "",
2269 (unsigned int) res
->res_info
.version
);
2277 case RES_TYPE_ACCELERATOR
:
2278 write_rc_accelerators (e
, res
->u
.acc
);
2281 case RES_TYPE_CURSOR
:
2282 write_rc_cursor (e
, res
->u
.cursor
);
2285 case RES_TYPE_GROUP_CURSOR
:
2286 write_rc_group_cursor (e
, res
->u
.group_cursor
);
2289 case RES_TYPE_DIALOG
:
2290 write_rc_dialog (e
, res
->u
.dialog
);
2293 case RES_TYPE_FONTDIR
:
2294 write_rc_fontdir (e
, res
->u
.fontdir
);
2297 case RES_TYPE_GROUP_ICON
:
2298 write_rc_group_icon (e
, res
->u
.group_icon
);
2302 write_rc_menu (e
, res
->u
.menu
, menuex
);
2305 case RES_TYPE_RCDATA
:
2306 write_rc_rcdata (e
, res
->u
.rcdata
, 0);
2309 case RES_TYPE_STRINGTABLE
:
2310 write_rc_stringtable (e
, name
, res
->u
.stringtable
);
2313 case RES_TYPE_USERDATA
:
2314 write_rc_rcdata (e
, res
->u
.userdata
, 0);
2317 case RES_TYPE_TOOLBAR
:
2318 write_rc_toolbar (e
, res
->u
.toolbar
);
2321 case RES_TYPE_VERSIONINFO
:
2322 write_rc_versioninfo (e
, res
->u
.versioninfo
);
2325 case RES_TYPE_BITMAP
:
2328 write_rc_datablock (e
, res
->u
.data
.length
, res
->u
.data
.data
, 0, 1, 0);
2330 case RES_TYPE_MESSAGETABLE
:
2331 write_rc_messagetable (e
, res
->u
.data
.length
, res
->u
.data
.data
);
2336 /* Write out accelerator information. */
2339 write_rc_accelerators (FILE *e
, const rc_accelerator
*accelerators
)
2341 const rc_accelerator
*acc
;
2343 fprintf (e
, "BEGIN\n");
2344 for (acc
= accelerators
; acc
!= NULL
; acc
= acc
->next
)
2350 if ((acc
->key
& 0x7f) == acc
->key
2351 && ISPRINT (acc
->key
)
2352 && (acc
->flags
& ACC_VIRTKEY
) == 0)
2354 fprintf (e
, "\"%c\"", (char) acc
->key
);
2359 fprintf (e
, "%d", (int) acc
->key
);
2363 fprintf (e
, ", %d", (int) acc
->id
);
2367 if ((acc
->flags
& ACC_VIRTKEY
) != 0)
2368 fprintf (e
, ", VIRTKEY");
2370 fprintf (e
, ", ASCII");
2373 if ((acc
->flags
& ACC_SHIFT
) != 0)
2374 fprintf (e
, ", SHIFT");
2375 if ((acc
->flags
& ACC_CONTROL
) != 0)
2376 fprintf (e
, ", CONTROL");
2377 if ((acc
->flags
& ACC_ALT
) != 0)
2378 fprintf (e
, ", ALT");
2383 fprintf (e
, "END\n");
2386 /* Write out cursor information. This would normally be in a separate
2387 file, which the rc file would include. */
2390 write_rc_cursor (FILE *e
, const rc_cursor
*cursor
)
2392 fprintf (e
, "BEGIN\n");
2394 fprintf (e
, " 0x%x, 0x%x,\t/* Hotspot x: %d, y: %d. */\n",
2395 (unsigned int) cursor
->xhotspot
, (unsigned int) cursor
->yhotspot
,
2396 (int) cursor
->xhotspot
, (int) cursor
->yhotspot
);
2397 write_rc_datablock (e
, (rc_uint_type
) cursor
->length
, (const bfd_byte
*) cursor
->data
,
2399 fprintf (e
, "END\n");
2402 /* Write out group cursor data. This would normally be built from the
2406 write_rc_group_cursor (FILE *e
, const rc_group_cursor
*group_cursor
)
2408 const rc_group_cursor
*gc
;
2411 for (c
= 0, gc
= group_cursor
; gc
!= NULL
; gc
= gc
->next
, c
++)
2413 fprintf (e
, "BEGIN\n");
2416 fprintf (e
, "0, 2, %d%s\t /* Having %d items. */\n", c
, (c
!= 0 ? "," : ""), c
);
2418 fprintf (e
, "/* width, height, planes, bits, bytes, index. */\n");
2420 for (c
= 1, gc
= group_cursor
; gc
!= NULL
; gc
= gc
->next
, c
++)
2423 fprintf (e
, "%d, %d, %d, %d, 0x%xL, %d%s /* Element %d. */\n",
2424 (int) gc
->width
, (int) gc
->height
, (int) gc
->planes
, (int) gc
->bits
,
2425 (unsigned int) gc
->bytes
, (int) gc
->index
, (gc
->next
!= NULL
? "," : ""), c
);
2426 fprintf (e
, "/* width: %d; height %d; planes %d; bits %d. */\n",
2427 (int) gc
->width
, (int) gc
->height
, (int) gc
->planes
,
2430 fprintf (e
, "END\n");
2433 /* Write dialog data. */
2436 write_rc_dialog (FILE *e
, const rc_dialog
*dialog
)
2438 const rc_dialog_control
*control
;
2440 fprintf (e
, "STYLE 0x%x\n", dialog
->style
);
2442 if (dialog
->exstyle
!= 0)
2443 fprintf (e
, "EXSTYLE 0x%x\n", (unsigned int) dialog
->exstyle
);
2445 if ((dialog
->class.named
&& dialog
->class.u
.n
.length
> 0)
2446 || dialog
->class.u
.id
!= 0)
2448 fprintf (e
, "CLASS ");
2449 res_id_print (e
, dialog
->class, 1);
2453 if (dialog
->caption
!= NULL
)
2455 fprintf (e
, "CAPTION ");
2456 unicode_print_quoted (e
, dialog
->caption
, -1);
2460 if ((dialog
->menu
.named
&& dialog
->menu
.u
.n
.length
> 0)
2461 || dialog
->menu
.u
.id
!= 0)
2463 fprintf (e
, "MENU ");
2464 res_id_print (e
, dialog
->menu
, 0);
2468 if (dialog
->font
!= NULL
)
2470 fprintf (e
, "FONT %d, ", (int) dialog
->pointsize
);
2471 unicode_print_quoted (e
, dialog
->font
, -1);
2472 if (dialog
->ex
!= NULL
2473 && (dialog
->ex
->weight
!= 0
2474 || dialog
->ex
->italic
!= 0
2475 || dialog
->ex
->charset
!= 1))
2476 fprintf (e
, ", %d, %d, %d",
2477 (int) dialog
->ex
->weight
,
2478 (int) dialog
->ex
->italic
,
2479 (int) dialog
->ex
->charset
);
2483 fprintf (e
, "BEGIN\n");
2485 for (control
= dialog
->controls
; control
!= NULL
; control
= control
->next
)
2486 write_rc_dialog_control (e
, control
);
2488 fprintf (e
, "END\n");
2491 /* For each predefined control keyword, this table provides the class
2497 unsigned short class;
2498 unsigned long style
;
2501 static const struct control_info control_info
[] =
2503 { "AUTO3STATE", CTL_BUTTON
, BS_AUTO3STATE
},
2504 { "AUTOCHECKBOX", CTL_BUTTON
, BS_AUTOCHECKBOX
},
2505 { "AUTORADIOBUTTON", CTL_BUTTON
, BS_AUTORADIOBUTTON
},
2506 { "CHECKBOX", CTL_BUTTON
, BS_CHECKBOX
},
2507 { "COMBOBOX", CTL_COMBOBOX
, (unsigned long) -1 },
2508 { "CTEXT", CTL_STATIC
, SS_CENTER
},
2509 { "DEFPUSHBUTTON", CTL_BUTTON
, BS_DEFPUSHBUTTON
},
2510 { "EDITTEXT", CTL_EDIT
, (unsigned long) -1 },
2511 { "GROUPBOX", CTL_BUTTON
, BS_GROUPBOX
},
2512 { "ICON", CTL_STATIC
, SS_ICON
},
2513 { "LISTBOX", CTL_LISTBOX
, (unsigned long) -1 },
2514 { "LTEXT", CTL_STATIC
, SS_LEFT
},
2515 { "PUSHBOX", CTL_BUTTON
, BS_PUSHBOX
},
2516 { "PUSHBUTTON", CTL_BUTTON
, BS_PUSHBUTTON
},
2517 { "RADIOBUTTON", CTL_BUTTON
, BS_RADIOBUTTON
},
2518 { "RTEXT", CTL_STATIC
, SS_RIGHT
},
2519 { "SCROLLBAR", CTL_SCROLLBAR
, (unsigned long) -1 },
2520 { "STATE3", CTL_BUTTON
, BS_3STATE
},
2521 /* It's important that USERBUTTON come after all the other button
2522 types, so that it won't be matched too early. */
2523 { "USERBUTTON", CTL_BUTTON
, (unsigned long) -1 },
2527 /* Write a dialog control. */
2530 write_rc_dialog_control (FILE *e
, const rc_dialog_control
*control
)
2532 const struct control_info
*ci
;
2536 if (control
->class.named
)
2540 for (ci
= control_info
; ci
->name
!= NULL
; ++ci
)
2541 if (ci
->class == control
->class.u
.id
2542 && (ci
->style
== (unsigned long) -1
2543 || ci
->style
== (control
->style
& 0xff)))
2547 fprintf (e
, "CONTROL");
2548 else if (ci
->name
!= NULL
)
2549 fprintf (e
, "%s", ci
->name
);
2552 fprintf (e
, "CONTROL");
2556 if (control
->text
.named
|| control
->text
.u
.id
!= 0)
2559 res_id_print (e
, control
->text
, 1);
2563 fprintf (e
, " %d, ", (int) control
->id
);
2567 if (control
->class.named
)
2569 res_id_print (e
, control
->class, 0);
2570 if (control
->class.named
)
2572 fprintf (e
, ", 0x%x, ", (unsigned int) control
->style
);
2575 fprintf (e
, "%d, %d", (int) control
->x
, (int) control
->y
);
2577 if (control
->style
!= SS_ICON
2578 || control
->exstyle
!= 0
2579 || control
->width
!= 0
2580 || control
->height
!= 0
2581 || control
->help
!= 0)
2583 fprintf (e
, ", %d, %d", (int) control
->width
, (int) control
->height
);
2585 /* FIXME: We don't need to print the style if it is the default.
2586 More importantly, in certain cases we actually need to turn
2587 off parts of the forced style, by using NOT. */
2589 fprintf (e
, ", 0x%x", (unsigned int) control
->style
);
2591 if (control
->exstyle
!= 0 || control
->help
!= 0)
2592 fprintf (e
, ", 0x%x, %u", (unsigned int) control
->exstyle
,
2593 (unsigned int) control
->help
);
2598 if (control
->data
!= NULL
)
2599 write_rc_rcdata (e
, control
->data
, 2);
2602 /* Write out font directory data. This would normally be built from
2606 write_rc_fontdir (FILE *e
, const rc_fontdir
*fontdir
)
2608 const rc_fontdir
*fc
;
2611 for (c
= 0, fc
= fontdir
; fc
!= NULL
; fc
= fc
->next
, c
++)
2613 fprintf (e
, "BEGIN\n");
2615 fprintf (e
, "%d%s\t /* Has %d elements. */\n", c
, (c
!= 0 ? "," : ""), c
);
2616 for (c
= 1, fc
= fontdir
; fc
!= NULL
; fc
= fc
->next
, c
++)
2619 fprintf (e
, "%d,\t/* Font no %d with index %d. */\n",
2620 (int) fc
->index
, c
, (int) fc
->index
);
2621 write_rc_datablock (e
, (rc_uint_type
) fc
->length
- 2,
2622 (const bfd_byte
*) fc
->data
+ 4,fc
->next
!= NULL
,
2625 fprintf (e
, "END\n");
2628 /* Write out group icon data. This would normally be built from the
2632 write_rc_group_icon (FILE *e
, const rc_group_icon
*group_icon
)
2634 const rc_group_icon
*gi
;
2637 for (c
= 0, gi
= group_icon
; gi
!= NULL
; gi
= gi
->next
, c
++)
2640 fprintf (e
, "BEGIN\n");
2642 fprintf (e
, " 0, 1, %d%s\t /* Has %d elements. */\n", c
, (c
!= 0 ? "," : ""), c
);
2645 fprintf (e
, "/* \"width height colors pad\", planes, bits, bytes, index. */\n");
2646 for (c
= 1, gi
= group_icon
; gi
!= NULL
; gi
= gi
->next
, c
++)
2649 fprintf (e
, "\"\\%03o\\%03o\\%03o\\%03o\", %d, %d, 0x%xL, %d%s\t/* Element no %d. */\n",
2650 gi
->width
, gi
->height
, gi
->colors
, 0, (int) gi
->planes
, (int) gi
->bits
,
2651 (unsigned int) gi
->bytes
, (int) gi
->index
, (gi
->next
!= NULL
? "," : ""), c
);
2653 fprintf (e
, "END\n");
2656 /* Write out a menu resource. */
2659 write_rc_menu (FILE *e
, const rc_menu
*menu
, int menuex
)
2661 if (menu
->help
!= 0)
2662 fprintf (e
, "// Help ID: %u\n", (unsigned int) menu
->help
);
2663 write_rc_menuitems (e
, menu
->items
, menuex
, 0);
2667 write_rc_toolbar (FILE *e
, const rc_toolbar
*tb
)
2669 rc_toolbar_item
*it
;
2671 fprintf (e
, "BEGIN\n");
2676 if (it
->id
.u
.id
== 0)
2677 fprintf (e
, "SEPARATOR\n");
2679 fprintf (e
, "BUTTON %d\n", (int) it
->id
.u
.id
);
2683 fprintf (e
, "END\n");
2686 /* Write out menuitems. */
2689 write_rc_menuitems (FILE *e
, const rc_menuitem
*menuitems
, int menuex
,
2692 const rc_menuitem
*mi
;
2695 fprintf (e
, "BEGIN\n");
2697 for (mi
= menuitems
; mi
!= NULL
; mi
= mi
->next
)
2699 indent (e
, ind
+ 2);
2701 if (mi
->popup
== NULL
)
2702 fprintf (e
, "MENUITEM");
2704 fprintf (e
, "POPUP");
2707 && mi
->popup
== NULL
2712 fprintf (e
, " SEPARATOR\n");
2716 if (mi
->text
== NULL
)
2717 fprintf (e
, " \"\"");
2721 unicode_print_quoted (e
, mi
->text
, -1);
2726 if (mi
->popup
== NULL
)
2727 fprintf (e
, ", %d", (int) mi
->id
);
2729 if ((mi
->type
& MENUITEM_CHECKED
) != 0)
2730 fprintf (e
, ", CHECKED");
2731 if ((mi
->type
& MENUITEM_GRAYED
) != 0)
2732 fprintf (e
, ", GRAYED");
2733 if ((mi
->type
& MENUITEM_HELP
) != 0)
2734 fprintf (e
, ", HELP");
2735 if ((mi
->type
& MENUITEM_INACTIVE
) != 0)
2736 fprintf (e
, ", INACTIVE");
2737 if ((mi
->type
& MENUITEM_MENUBARBREAK
) != 0)
2738 fprintf (e
, ", MENUBARBREAK");
2739 if ((mi
->type
& MENUITEM_MENUBREAK
) != 0)
2740 fprintf (e
, ", MENUBREAK");
2744 if (mi
->id
!= 0 || mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2746 fprintf (e
, ", %d", (int) mi
->id
);
2747 if (mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2749 fprintf (e
, ", %u", (unsigned int) mi
->type
);
2750 if (mi
->state
!= 0 || mi
->help
!= 0)
2752 fprintf (e
, ", %u", (unsigned int) mi
->state
);
2754 fprintf (e
, ", %u", (unsigned int) mi
->help
);
2762 if (mi
->popup
!= NULL
)
2763 write_rc_menuitems (e
, mi
->popup
, menuex
, ind
+ 2);
2767 fprintf (e
, "END\n");
2771 test_rc_datablock_unicode (rc_uint_type length
, const bfd_byte
*data
)
2774 if ((length
& 1) != 0)
2777 for (i
= 0; i
< length
; i
+= 2)
2779 if (data
[i
] == 0 && data
[i
+ 1] == 0 && (i
+ 2) < length
)
2781 if (data
[i
] == 0xff && data
[i
+ 1] == 0xff)
2788 test_rc_datablock_text (rc_uint_type length
, const bfd_byte
*data
)
2798 for (i
= 0, c
= 0; i
< length
; i
++)
2800 if (! ISPRINT (data
[i
]) && data
[i
] != '\n'
2801 && ! (data
[i
] == '\r' && (i
+ 1) < length
&& data
[i
+ 1] == '\n')
2803 && ! (data
[i
] == 0 && (i
+ 1) != length
))
2809 else if (data
[i
] == '\n') has_nl
++;
2811 if (length
> 80 && ! has_nl
)
2813 c
= (((c
* 10000) + (i
/ 100) - 1)) / i
;
2820 write_rc_messagetable (FILE *e
, rc_uint_type length
, const bfd_byte
*data
)
2823 const struct bin_messagetable
*mt
;
2824 fprintf (e
, "BEGIN\n");
2826 write_rc_datablock (e
, length
, data
, 0, 0, 0);
2829 wr_printcomment (e
, "MC syntax dump");
2830 if (length
< BIN_MESSAGETABLE_SIZE
)
2835 mt
= (const struct bin_messagetable
*) data
;
2836 m
= windres_get_32 (&wrtarget
, mt
->cblocks
, length
);
2837 if (length
< (BIN_MESSAGETABLE_SIZE
+ m
* BIN_MESSAGETABLE_BLOCK_SIZE
))
2842 for (i
= 0; i
< m
; i
++)
2844 rc_uint_type low
, high
, offset
;
2845 const struct bin_messagetable_item
*mti
;
2847 low
= windres_get_32 (&wrtarget
, mt
->items
[i
].lowid
, 4);
2848 high
= windres_get_32 (&wrtarget
, mt
->items
[i
].highid
, 4);
2849 offset
= windres_get_32 (&wrtarget
, mt
->items
[i
].offset
, 4);
2852 rc_uint_type elen
, flags
;
2853 if ((offset
+ BIN_MESSAGETABLE_ITEM_SIZE
) > length
)
2858 mti
= (const struct bin_messagetable_item
*) &data
[offset
];
2859 elen
= windres_get_16 (&wrtarget
, mti
->length
, 2);
2860 flags
= windres_get_16 (&wrtarget
, mti
->flags
, 2);
2861 if ((offset
+ elen
) > length
)
2866 wr_printcomment (e
, "MessageId = 0x%x", low
);
2867 wr_printcomment (e
, "");
2868 if ((flags
& MESSAGE_RESOURCE_UNICODE
) == MESSAGE_RESOURCE_UNICODE
)
2869 unicode_print (e
, (const unichar
*) mti
->data
,
2870 (elen
- BIN_MESSAGETABLE_ITEM_SIZE
) / 2);
2872 ascii_print (e
, (const char *) mti
->data
,
2873 (elen
- BIN_MESSAGETABLE_ITEM_SIZE
));
2874 wr_printcomment (e
,"");
2881 wr_printcomment (e
, "Illegal data");
2883 fprintf (e
, "END\n");
2887 write_rc_datablock (FILE *e
, rc_uint_type length
, const bfd_byte
*data
, int has_next
,
2888 int hasblock
, int show_comment
)
2893 fprintf (e
, "BEGIN\n");
2895 if (show_comment
== -1)
2897 if (test_rc_datablock_text(length
, data
))
2900 for (i
= 0; i
< length
;)
2905 for (c
= 0; i
< length
&& c
< 160 && data
[i
] != '\n'; c
++, i
++)
2907 if (i
< length
&& data
[i
] == '\n')
2909 ascii_print (e
, (const char *) &data
[i
- c
], c
);
2918 fprintf (e
, "\"\"");
2924 fprintf (e
, "END\n");
2927 if (test_rc_datablock_unicode (length
, data
))
2930 for (i
= 0; i
< length
;)
2934 u
= (const unichar
*) &data
[i
];
2938 for (c
= 0; i
< length
&& c
< 160 && u
[c
] != '\n'; c
++, i
+= 2)
2940 if (i
< length
&& u
[c
] == '\n')
2942 unicode_print (e
, u
, c
);
2951 fprintf (e
, "L\"\"");
2957 fprintf (e
, "END\n");
2966 rc_uint_type i
, max_row
;
2969 max_row
= (show_comment
? 4 : 8);
2971 for (i
= 0; i
+ 3 < length
;)
2974 rc_uint_type comment_start
;
2981 for (k
= 0; k
< max_row
&& i
+ 3 < length
; k
++, i
+= 4)
2984 plen
= fprintf (e
, "0x%lxL",
2985 (long) windres_get_32 (&wrtarget
, data
+ i
, length
- i
));
2987 plen
= fprintf (e
, " 0x%lxL",
2988 (long) windres_get_32 (&wrtarget
, data
+ i
, length
- i
)) - 1;
2989 if (has_next
|| (i
+ 4) < length
)
2991 if (plen
>0 && plen
< 11)
2992 indent (e
, 11 - plen
);
2998 fprintf (e
, "\t/* ");
2999 ascii_print (e
, (const char *) &data
[comment_start
], i
- comment_start
);
3000 fprintf (e
, ". */");
3010 plen
= fprintf (e
, "0x%x",
3011 (int) windres_get_16 (&wrtarget
, data
+ i
, length
- i
));
3012 if (has_next
|| i
+ 2 < length
)
3014 if (plen
> 0 && plen
< 11)
3015 indent (e
, 11 - plen
);
3020 fprintf (e
, "\t/* ");
3021 ascii_print (e
, (const char *) &data
[i
], 2);
3022 fprintf (e
, ". */");
3034 ascii_print (e
, (const char *) &data
[i
], 1);
3043 fprintf (e
, "END\n");
3046 /* Write out an rcdata resource. This is also used for other types of
3047 resources that need to print arbitrary data. */
3050 write_rc_rcdata (FILE *e
, const rc_rcdata_item
*rcdata
, int ind
)
3052 const rc_rcdata_item
*ri
;
3055 fprintf (e
, "BEGIN\n");
3057 for (ri
= rcdata
; ri
!= NULL
; ri
= ri
->next
)
3059 if (ri
->type
== RCDATA_BUFFER
&& ri
->u
.buffer
.length
== 0)
3068 indent (e
, ind
+ 2);
3069 fprintf (e
, "%ld", (long) (ri
->u
.word
& 0xffff));
3073 indent (e
, ind
+ 2);
3074 fprintf (e
, "%luL", (unsigned long) ri
->u
.dword
);
3078 indent (e
, ind
+ 2);
3080 ascii_print (e
, ri
->u
.string
.s
, ri
->u
.string
.length
);
3084 case RCDATA_WSTRING
:
3085 indent (e
, ind
+ 2);
3087 unicode_print (e
, ri
->u
.wstring
.w
, ri
->u
.wstring
.length
);
3092 write_rc_datablock (e
, (rc_uint_type
) ri
->u
.buffer
.length
,
3093 (const bfd_byte
*) ri
->u
.buffer
.data
,
3094 ri
->next
!= NULL
, 0, -1);
3098 if (ri
->type
!= RCDATA_BUFFER
)
3100 if (ri
->next
!= NULL
)
3107 fprintf (e
, "END\n");
3110 /* Write out a stringtable resource. */
3113 write_rc_stringtable (FILE *e
, const rc_res_id
*name
,
3114 const rc_stringtable
*stringtable
)
3116 rc_uint_type offset
;
3119 if (name
!= NULL
&& ! name
->named
)
3120 offset
= (name
->u
.id
- 1) << 4;
3123 fprintf (e
, "/* %s string table name. */\n",
3124 name
== NULL
? "Missing" : "Invalid");
3128 fprintf (e
, "BEGIN\n");
3130 for (i
= 0; i
< 16; i
++)
3132 if (stringtable
->strings
[i
].length
!= 0)
3134 fprintf (e
, " %lu, ", (long) offset
+ i
);
3135 unicode_print_quoted (e
, stringtable
->strings
[i
].string
,
3136 stringtable
->strings
[i
].length
);
3141 fprintf (e
, "END\n");
3144 /* Write out a versioninfo resource. */
3147 write_rc_versioninfo (FILE *e
, const rc_versioninfo
*versioninfo
)
3149 const rc_fixed_versioninfo
*f
;
3150 const rc_ver_info
*vi
;
3152 f
= versioninfo
->fixed
;
3153 if (f
->file_version_ms
!= 0 || f
->file_version_ls
!= 0)
3154 fprintf (e
, " FILEVERSION %u, %u, %u, %u\n",
3155 (unsigned int) ((f
->file_version_ms
>> 16) & 0xffff),
3156 (unsigned int) (f
->file_version_ms
& 0xffff),
3157 (unsigned int) ((f
->file_version_ls
>> 16) & 0xffff),
3158 (unsigned int) (f
->file_version_ls
& 0xffff));
3159 if (f
->product_version_ms
!= 0 || f
->product_version_ls
!= 0)
3160 fprintf (e
, " PRODUCTVERSION %u, %u, %u, %u\n",
3161 (unsigned int) ((f
->product_version_ms
>> 16) & 0xffff),
3162 (unsigned int) (f
->product_version_ms
& 0xffff),
3163 (unsigned int) ((f
->product_version_ls
>> 16) & 0xffff),
3164 (unsigned int) (f
->product_version_ls
& 0xffff));
3165 if (f
->file_flags_mask
!= 0)
3166 fprintf (e
, " FILEFLAGSMASK 0x%x\n", (unsigned int) f
->file_flags_mask
);
3167 if (f
->file_flags
!= 0)
3168 fprintf (e
, " FILEFLAGS 0x%x\n", (unsigned int) f
->file_flags
);
3169 if (f
->file_os
!= 0)
3170 fprintf (e
, " FILEOS 0x%x\n", (unsigned int) f
->file_os
);
3171 if (f
->file_type
!= 0)
3172 fprintf (e
, " FILETYPE 0x%x\n", (unsigned int) f
->file_type
);
3173 if (f
->file_subtype
!= 0)
3174 fprintf (e
, " FILESUBTYPE 0x%x\n", (unsigned int) f
->file_subtype
);
3175 if (f
->file_date_ms
!= 0 || f
->file_date_ls
!= 0)
3176 fprintf (e
, "/* Date: %u, %u. */\n",
3177 (unsigned int) f
->file_date_ms
, (unsigned int) f
->file_date_ls
);
3179 fprintf (e
, "BEGIN\n");
3181 for (vi
= versioninfo
->var
; vi
!= NULL
; vi
= vi
->next
)
3185 case VERINFO_STRING
:
3187 const rc_ver_stringinfo
*vs
;
3189 fprintf (e
, " BLOCK \"StringFileInfo\"\n");
3190 fprintf (e
, " BEGIN\n");
3191 fprintf (e
, " BLOCK ");
3192 unicode_print_quoted (e
, vi
->u
.string
.language
, -1);
3194 fprintf (e
, " BEGIN\n");
3196 for (vs
= vi
->u
.string
.strings
; vs
!= NULL
; vs
= vs
->next
)
3198 fprintf (e
, " VALUE ");
3199 unicode_print_quoted (e
, vs
->key
, -1);
3201 unicode_print_quoted (e
, vs
->value
, -1);
3205 fprintf (e
, " END\n");
3206 fprintf (e
, " END\n");
3212 const rc_ver_varinfo
*vv
;
3214 fprintf (e
, " BLOCK \"VarFileInfo\"\n");
3215 fprintf (e
, " BEGIN\n");
3216 fprintf (e
, " VALUE ");
3217 unicode_print_quoted (e
, vi
->u
.var
.key
, -1);
3219 for (vv
= vi
->u
.var
.var
; vv
!= NULL
; vv
= vv
->next
)
3220 fprintf (e
, ", 0x%x, %d", (unsigned int) vv
->language
,
3223 fprintf (e
, "\n END\n");
3230 fprintf (e
, "END\n");
3234 rcdata_copy (const rc_rcdata_item
*src
, bfd_byte
*dst
)
3242 windres_put_16 (&wrtarget
, dst
, (rc_uint_type
) src
->u
.word
);
3246 windres_put_32 (&wrtarget
, dst
, (rc_uint_type
) src
->u
.dword
);
3249 if (dst
&& src
->u
.string
.length
)
3250 memcpy (dst
, src
->u
.string
.s
, src
->u
.string
.length
);
3251 return (rc_uint_type
) src
->u
.string
.length
;
3252 case RCDATA_WSTRING
:
3253 if (dst
&& src
->u
.wstring
.length
)
3254 memcpy (dst
, src
->u
.wstring
.w
, src
->u
.wstring
.length
* sizeof (unichar
));
3255 return (rc_uint_type
) (src
->u
.wstring
.length
* sizeof (unichar
));
3257 if (dst
&& src
->u
.buffer
.length
)
3258 memcpy (dst
, src
->u
.buffer
.data
, src
->u
.buffer
.length
);
3259 return (rc_uint_type
) src
->u
.buffer
.length
;
3263 /* Never reached. */