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 /* Determine if FILENAME contains special characters that
355 can cause problems unless the entire filename is quoted. */
358 filename_need_quotes (const char *filename
)
360 if (filename
== NULL
|| (filename
[0] == '-' && filename
[1] == 0))
363 while (*filename
!= 0)
380 /* Look for the preprocessor program. */
383 look_for_default (char *cmd
, const char *prefix
, int end_prefix
,
384 const char *preprocargs
, const char *filename
)
389 const char *fnquotes
= (filename_need_quotes (filename
) ? "\"" : "");
391 strcpy (cmd
, prefix
);
393 sprintf (cmd
+ end_prefix
, "%s", DEFAULT_PREPROCESSOR
);
394 space
= strchr (cmd
+ end_prefix
, ' ');
399 #if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32)
400 strchr (cmd
, '\\') ||
404 found
= (stat (cmd
, &s
) == 0
405 #ifdef HAVE_EXECUTABLE_SUFFIX
406 || stat (strcat (cmd
, EXECUTABLE_SUFFIX
), &s
) == 0
413 fprintf (stderr
, _("Tried `%s'\n"), cmd
);
418 strcpy (cmd
, prefix
);
420 sprintf (cmd
+ end_prefix
, "%s %s %s%s%s",
421 DEFAULT_PREPROCESSOR
, preprocargs
, fnquotes
, filename
, fnquotes
);
424 fprintf (stderr
, _("Using `%s'\n"), cmd
);
426 cpp_pipe
= open_input_stream (cmd
);
430 /* Read an rc file. */
433 read_rc_file (const char *filename
, const char *preprocessor
,
434 const char *preprocargs
, int language
, int use_temp_file
)
437 const char *fnquotes
= (filename_need_quotes (filename
) ? "\"" : "");
439 istream_type
= (use_temp_file
) ? ISTREAM_FILE
: ISTREAM_PIPE
;
441 if (preprocargs
== NULL
)
443 if (filename
== NULL
)
448 cmd
= xmalloc (strlen (preprocessor
)
449 + strlen (preprocargs
)
451 + strlen (fnquotes
) * 2
453 sprintf (cmd
, "%s %s %s%s%s", preprocessor
, preprocargs
,
454 fnquotes
, filename
, fnquotes
);
456 cpp_pipe
= open_input_stream (cmd
);
460 char *dash
, *slash
, *cp
;
462 preprocessor
= DEFAULT_PREPROCESSOR
;
464 cmd
= xmalloc (strlen (program_name
)
465 + strlen (preprocessor
)
466 + strlen (preprocargs
)
468 + strlen (fnquotes
) * 2
469 #ifdef HAVE_EXECUTABLE_SUFFIX
470 + strlen (EXECUTABLE_SUFFIX
)
476 for (cp
= program_name
; *cp
; cp
++)
481 #if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32)
482 *cp
== ':' || *cp
== '\\' ||
495 /* First, try looking for a prefixed gcc in the windres
496 directory, with the same prefix as windres */
498 cpp_pipe
= look_for_default (cmd
, program_name
, dash
- program_name
+ 1,
499 preprocargs
, filename
);
502 if (slash
&& ! cpp_pipe
)
504 /* Next, try looking for a gcc in the same directory as
507 cpp_pipe
= look_for_default (cmd
, program_name
, slash
- program_name
+ 1,
508 preprocargs
, filename
);
513 /* Sigh, try the default */
515 cpp_pipe
= look_for_default (cmd
, "", 0, preprocargs
, filename
);
522 rc_filename
= xstrdup (filename
);
525 rcparse_set_language (language
);
527 rcparse_discard_strings ();
529 close_input_stream ();
531 if (fontdirs
!= NULL
)
540 /* Close the input stream if it is open. */
543 close_input_stream (void)
545 if (istream_type
== ISTREAM_FILE
)
547 if (cpp_pipe
!= NULL
)
550 if (cpp_temp_file
!= NULL
)
552 int errno_save
= errno
;
554 unlink (cpp_temp_file
);
556 free (cpp_temp_file
);
561 if (cpp_pipe
!= NULL
)
565 /* Since this is also run via xatexit, safeguard. */
567 cpp_temp_file
= NULL
;
570 /* Report an error while reading an rc file. */
573 yyerror (const char *msg
)
575 fatal ("%s:%d: %s", rc_filename
, rc_lineno
, msg
);
578 /* Issue a warning while reading an rc file. */
581 rcparse_warning (const char *msg
)
583 fprintf (stderr
, _("%s:%d: %s\n"), rc_filename
, rc_lineno
, msg
);
586 /* Die if we get an unexpected end of file. */
589 unexpected_eof (const char *msg
)
591 fatal (_("%s: unexpected EOF"), msg
);
594 /* Read a 16 bit word from a file. The data is assumed to be little
598 get_word (FILE *e
, const char *msg
)
605 unexpected_eof (msg
);
606 return ((b2
& 0xff) << 8) | (b1
& 0xff);
609 /* Read a 32 bit word from a file. The data is assumed to be little
613 get_long (FILE *e
, const char *msg
)
622 unexpected_eof (msg
);
623 return (((((((b4
& 0xff) << 8)
629 /* Read data from a file. This is a wrapper to do error checking. */
632 get_data (FILE *e
, bfd_byte
*p
, rc_uint_type c
, const char *msg
)
634 rc_uint_type got
; // $$$d
636 got
= (rc_uint_type
) fread (p
, 1, c
, e
);
640 fatal (_("%s: read of %lu returned %lu"), msg
, (long) c
, (long) got
);
643 /* Define an accelerator resource. */
646 define_accelerator (rc_res_id id
, const rc_res_res_info
*resinfo
,
647 rc_accelerator
*data
)
651 r
= define_standard_resource (&resources
, RT_ACCELERATOR
, id
,
652 resinfo
->language
, 0);
653 r
->type
= RES_TYPE_ACCELERATOR
;
655 r
->res_info
= *resinfo
;
658 /* Define a bitmap resource. Bitmap data is stored in a file. The
659 first 14 bytes of the file are a standard header, which is not
660 included in the resource data. */
662 #define BITMAP_SKIP (14)
665 define_bitmap (rc_res_id id
, const rc_res_res_info
*resinfo
,
666 const char *filename
)
675 e
= open_file_search (filename
, FOPEN_RB
, "bitmap file", &real_filename
);
677 if (stat (real_filename
, &s
) < 0)
678 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
681 data
= (bfd_byte
*) res_alloc (s
.st_size
- BITMAP_SKIP
);
683 for (i
= 0; i
< BITMAP_SKIP
; i
++)
686 get_data (e
, data
, s
.st_size
- BITMAP_SKIP
, real_filename
);
689 free (real_filename
);
691 r
= define_standard_resource (&resources
, RT_BITMAP
, id
,
692 resinfo
->language
, 0);
694 r
->type
= RES_TYPE_BITMAP
;
695 r
->u
.data
.length
= s
.st_size
- BITMAP_SKIP
;
696 r
->u
.data
.data
= data
;
697 r
->res_info
= *resinfo
;
700 /* Define a cursor resource. A cursor file may contain a set of
701 bitmaps, each representing the same cursor at various different
702 resolutions. They each get written out with a different ID. The
703 real cursor resource is then a group resource which can be used to
704 select one of the actual cursors. */
707 define_cursor (rc_res_id id
, const rc_res_res_info
*resinfo
,
708 const char *filename
)
713 struct icondir
*icondirs
;
716 rc_group_cursor
*first
, **pp
;
718 e
= open_file_search (filename
, FOPEN_RB
, "cursor file", &real_filename
);
720 /* A cursor file is basically an icon file. The start of the file
721 is a three word structure. The first word is ignored. The
722 second word is the type of data. The third word is the number of
725 get_word (e
, real_filename
);
726 type
= get_word (e
, real_filename
);
727 count
= get_word (e
, real_filename
);
729 fatal (_("cursor file `%s' does not contain cursor data"), real_filename
);
731 /* Read in the icon directory entries. */
733 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
735 for (i
= 0; i
< count
; i
++)
737 icondirs
[i
].width
= getc (e
);
738 icondirs
[i
].height
= getc (e
);
739 icondirs
[i
].colorcount
= getc (e
);
741 icondirs
[i
].u
.cursor
.xhotspot
= get_word (e
, real_filename
);
742 icondirs
[i
].u
.cursor
.yhotspot
= get_word (e
, real_filename
);
743 icondirs
[i
].bytes
= get_long (e
, real_filename
);
744 icondirs
[i
].offset
= get_long (e
, real_filename
);
747 unexpected_eof (real_filename
);
750 /* Define each cursor as a unique resource. */
752 first_cursor
= cursors
;
754 for (i
= 0; i
< count
; i
++)
760 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
761 fatal (_("%s: fseek to %lu failed: %s"), real_filename
,
762 icondirs
[i
].offset
, strerror (errno
));
764 data
= (bfd_byte
*) res_alloc (icondirs
[i
].bytes
);
766 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
768 c
= (rc_cursor
*) res_alloc (sizeof (rc_cursor
));
769 c
->xhotspot
= icondirs
[i
].u
.cursor
.xhotspot
;
770 c
->yhotspot
= icondirs
[i
].u
.cursor
.yhotspot
;
771 c
->length
= icondirs
[i
].bytes
;
779 r
= define_standard_resource (&resources
, RT_CURSOR
, name
,
780 resinfo
->language
, 0);
781 r
->type
= RES_TYPE_CURSOR
;
783 r
->res_info
= *resinfo
;
787 free (real_filename
);
789 /* Define a cursor group resource. */
793 for (i
= 0; i
< count
; i
++)
797 cg
= (rc_group_cursor
*) res_alloc (sizeof (rc_group_cursor
));
799 cg
->width
= icondirs
[i
].width
;
800 cg
->height
= 2 * icondirs
[i
].height
;
802 /* FIXME: What should these be set to? */
806 cg
->bytes
= icondirs
[i
].bytes
+ 4;
807 cg
->index
= first_cursor
+ i
+ 1;
815 r
= define_standard_resource (&resources
, RT_GROUP_CURSOR
, id
,
816 resinfo
->language
, 0);
817 r
->type
= RES_TYPE_GROUP_CURSOR
;
818 r
->u
.group_cursor
= first
;
819 r
->res_info
= *resinfo
;
822 /* Define a dialog resource. */
825 define_dialog (rc_res_id id
, const rc_res_res_info
*resinfo
,
826 const rc_dialog
*dialog
)
831 copy
= (rc_dialog
*) res_alloc (sizeof *copy
);
834 r
= define_standard_resource (&resources
, RT_DIALOG
, id
,
835 resinfo
->language
, 0);
836 r
->type
= RES_TYPE_DIALOG
;
838 r
->res_info
= *resinfo
;
841 /* Define a dialog control. This does not define a resource, but
842 merely allocates and fills in a structure. */
845 define_control (const rc_res_id iid
, rc_uint_type id
, rc_uint_type x
,
846 rc_uint_type y
, rc_uint_type width
, rc_uint_type height
,
847 const rc_res_id
class, rc_uint_type style
,
848 rc_uint_type exstyle
)
850 rc_dialog_control
*n
;
852 n
= (rc_dialog_control
*) res_alloc (sizeof (rc_dialog_control
));
856 n
->exstyle
= exstyle
;
870 define_icon_control (rc_res_id iid
, rc_uint_type id
, rc_uint_type x
,
871 rc_uint_type y
, rc_uint_type style
,
872 rc_uint_type exstyle
, rc_uint_type help
,
873 rc_rcdata_item
*data
, rc_dialog_ex
*ex
)
875 rc_dialog_control
*n
;
880 style
= SS_ICON
| WS_CHILD
| WS_VISIBLE
;
881 res_string_to_id (&tid
, "");
883 cid
.u
.id
= CTL_STATIC
;
884 n
= define_control (tid
, id
, x
, y
, 0, 0, cid
, style
, exstyle
);
887 rcparse_warning (_("help ID requires DIALOGEX"));
889 rcparse_warning (_("control data requires DIALOGEX"));
896 /* Define a font resource. */
899 define_font (rc_res_id id
, const rc_res_res_info
*resinfo
,
900 const char *filename
)
911 const char *device
, *face
;
914 e
= open_file_search (filename
, FOPEN_RB
, "font file", &real_filename
);
916 if (stat (real_filename
, &s
) < 0)
917 fatal (_("stat failed on font file `%s': %s"), real_filename
,
920 data
= (bfd_byte
*) res_alloc (s
.st_size
);
922 get_data (e
, data
, s
.st_size
, real_filename
);
925 free (real_filename
);
927 r
= define_standard_resource (&resources
, RT_FONT
, id
,
928 resinfo
->language
, 0);
930 r
->type
= RES_TYPE_FONT
;
931 r
->u
.data
.length
= s
.st_size
;
932 r
->u
.data
.data
= data
;
933 r
->res_info
= *resinfo
;
935 /* For each font resource, we must add an entry in the FONTDIR
936 resource. The FONTDIR resource includes some strings in the font
937 file. To find them, we have to do some magic on the data we have
940 offset
= ((((((data
[47] << 8)
944 if (offset
> 0 && offset
< s
.st_size
)
945 device
= (char *) data
+ offset
;
949 offset
= ((((((data
[51] << 8)
953 if (offset
> 0 && offset
< s
.st_size
)
954 face
= (char *) data
+ offset
;
960 fontdatalength
= 58 + strlen (device
) + strlen (face
);
961 fontdata
= (bfd_byte
*) res_alloc (fontdatalength
);
962 memcpy (fontdata
, data
, 56);
963 strcpy ((char *) fontdata
+ 56, device
);
964 strcpy ((char *) fontdata
+ 57 + strlen (device
), face
);
966 fd
= (rc_fontdir
*) res_alloc (sizeof (rc_fontdir
));
969 fd
->length
= fontdatalength
;
972 for (pp
= &fontdirs
; *pp
!= NULL
; pp
= &(*pp
)->next
)
976 /* For the single fontdirs resource, we always use the resource
977 information of the last font. I don't know what else to do. */
978 fontdirs_resinfo
= *resinfo
;
982 define_font_rcdata (rc_res_id id
,const rc_res_res_info
*resinfo
,
983 rc_rcdata_item
*data
)
986 rc_uint_type len_data
;
989 r
= define_standard_resource (&resources
, RT_FONT
, id
,
990 resinfo
->language
, 0);
992 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
994 r
->type
= RES_TYPE_FONT
;
995 r
->u
.data
.length
= len_data
;
996 r
->u
.data
.data
= pb_data
;
997 r
->res_info
= *resinfo
;
1000 /* Define the fontdirs resource. This is called after the entire rc
1001 file has been parsed, if any font resources were seen. */
1004 define_fontdirs (void)
1012 r
= define_standard_resource (&resources
, RT_FONTDIR
, id
, 0x409, 0);
1014 r
->type
= RES_TYPE_FONTDIR
;
1015 r
->u
.fontdir
= fontdirs
;
1016 r
->res_info
= fontdirs_resinfo
;
1020 rcdata_render_as_buffer (const rc_rcdata_item
*data
, rc_uint_type
*plen
)
1022 const rc_rcdata_item
*d
;
1023 bfd_byte
*ret
= NULL
, *pret
;
1024 rc_uint_type len
= 0;
1026 for (d
= data
; d
!= NULL
; d
= d
->next
)
1027 len
+= rcdata_copy (d
, NULL
);
1030 ret
= pret
= (bfd_byte
*) res_alloc (len
);
1031 for (d
= data
; d
!= NULL
; d
= d
->next
)
1032 pret
+= rcdata_copy (d
, pret
);
1040 define_fontdir_rcdata (rc_res_id id
,const rc_res_res_info
*resinfo
,
1041 rc_rcdata_item
*data
)
1044 rc_fontdir
*fd
, *fd_first
, *fd_cur
;
1045 rc_uint_type len_data
;
1049 fd_cur
= fd_first
= NULL
;
1050 r
= define_standard_resource (&resources
, RT_FONTDIR
, id
, 0x409, 0);
1052 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
1056 rc_uint_type off
= 2;
1057 c
= windres_get_16 (&wrtarget
, pb_data
, len_data
);
1061 rc_uint_type safe_pos
= off
;
1062 const struct bin_fontdir_item
*bfi
;
1064 bfi
= (const struct bin_fontdir_item
*) pb_data
+ off
;
1065 fd
= (rc_fontdir
*) res_alloc (sizeof (rc_fontdir
));
1066 fd
->index
= windres_get_16 (&wrtarget
, bfi
->index
, len_data
- off
);
1067 fd
->data
= pb_data
+ off
;
1069 len
= strlen ((char *) bfi
->device_name
) + 1;
1070 off
+= (rc_uint_type
) len
;
1071 off
+= (rc_uint_type
) strlen ((char *) bfi
->device_name
+ len
) + 1;
1072 fd
->length
= (off
- safe_pos
);
1074 if (fd_first
== NULL
)
1081 r
->type
= RES_TYPE_FONTDIR
;
1082 r
->u
.fontdir
= fd_first
;
1083 r
->res_info
= *resinfo
;
1086 static void define_messagetable_rcdata (rc_res_id id
, const rc_res_res_info
*resinfo
,
1087 rc_rcdata_item
*data
)
1090 rc_uint_type len_data
;
1093 r
= define_standard_resource (&resources
, RT_MESSAGETABLE
, id
, resinfo
->language
, 0);
1095 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
1096 r
->type
= RES_TYPE_MESSAGETABLE
;
1097 r
->u
.data
.length
= len_data
;
1098 r
->u
.data
.data
= pb_data
;
1099 r
->res_info
= *resinfo
;
1102 /* Define an icon resource. An icon file may contain a set of
1103 bitmaps, each representing the same icon at various different
1104 resolutions. They each get written out with a different ID. The
1105 real icon resource is then a group resource which can be used to
1106 select one of the actual icon bitmaps. */
1109 define_icon (rc_res_id id
, const rc_res_res_info
*resinfo
,
1110 const char *filename
)
1113 char *real_filename
;
1115 struct icondir
*icondirs
;
1118 rc_group_icon
*first
, **pp
;
1120 e
= open_file_search (filename
, FOPEN_RB
, "icon file", &real_filename
);
1122 /* The start of an icon file is a three word structure. The first
1123 word is ignored. The second word is the type of data. The third
1124 word is the number of entries. */
1126 get_word (e
, real_filename
);
1127 type
= get_word (e
, real_filename
);
1128 count
= get_word (e
, real_filename
);
1130 fatal (_("icon file `%s' does not contain icon data"), real_filename
);
1132 /* Read in the icon directory entries. */
1134 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
1136 for (i
= 0; i
< count
; i
++)
1138 icondirs
[i
].width
= getc (e
);
1139 icondirs
[i
].height
= getc (e
);
1140 icondirs
[i
].colorcount
= getc (e
);
1142 icondirs
[i
].u
.icon
.planes
= get_word (e
, real_filename
);
1143 icondirs
[i
].u
.icon
.bits
= get_word (e
, real_filename
);
1144 icondirs
[i
].bytes
= get_long (e
, real_filename
);
1145 icondirs
[i
].offset
= get_long (e
, real_filename
);
1148 unexpected_eof (real_filename
);
1151 /* Define each icon as a unique resource. */
1155 for (i
= 0; i
< count
; i
++)
1160 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
1161 fatal (_("%s: fseek to %lu failed: %s"), real_filename
,
1162 icondirs
[i
].offset
, strerror (errno
));
1164 data
= (bfd_byte
*) res_alloc (icondirs
[i
].bytes
);
1166 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
1173 r
= define_standard_resource (&resources
, RT_ICON
, name
,
1174 resinfo
->language
, 0);
1175 r
->type
= RES_TYPE_ICON
;
1176 r
->u
.data
.length
= icondirs
[i
].bytes
;
1177 r
->u
.data
.data
= data
;
1178 r
->res_info
= *resinfo
;
1182 free (real_filename
);
1184 /* Define an icon group resource. */
1188 for (i
= 0; i
< count
; i
++)
1192 /* For some reason, at least in some files the planes and bits
1193 are zero. We instead set them from the color. This is
1196 cg
= (rc_group_icon
*) res_alloc (sizeof (rc_group_icon
));
1198 cg
->width
= icondirs
[i
].width
;
1199 cg
->height
= icondirs
[i
].height
;
1200 cg
->colors
= icondirs
[i
].colorcount
;
1202 if (icondirs
[i
].u
.icon
.planes
)
1203 cg
->planes
= icondirs
[i
].u
.icon
.planes
;
1207 if (icondirs
[i
].u
.icon
.bits
)
1208 cg
->bits
= icondirs
[i
].u
.icon
.bits
;
1213 while ((1L << cg
->bits
) < cg
->colors
)
1217 cg
->bytes
= icondirs
[i
].bytes
;
1218 cg
->index
= first_icon
+ i
+ 1;
1226 r
= define_standard_resource (&resources
, RT_GROUP_ICON
, id
,
1227 resinfo
->language
, 0);
1228 r
->type
= RES_TYPE_GROUP_ICON
;
1229 r
->u
.group_icon
= first
;
1230 r
->res_info
= *resinfo
;
1234 define_group_icon_rcdata (rc_res_id id
, const rc_res_res_info
*resinfo
,
1235 rc_rcdata_item
*data
)
1238 rc_group_icon
*cg
, *first
, *cur
;
1239 rc_uint_type len_data
;
1242 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
1247 while (len_data
>= 6)
1250 unsigned short type
;
1251 type
= windres_get_16 (&wrtarget
, pb_data
+ 2, len_data
- 2);
1253 fatal (_("unexpected group icon type %d"), type
);
1254 c
= windres_get_16 (&wrtarget
, pb_data
+ 4, len_data
- 4);
1258 for (i
= 0; i
< c
; i
++)
1261 fatal ("too small group icon rcdata");
1262 cg
= (rc_group_icon
*) res_alloc (sizeof (rc_group_icon
));
1264 cg
->width
= pb_data
[0];
1265 cg
->height
= pb_data
[1];
1266 cg
->colors
= pb_data
[2];
1267 cg
->planes
= windres_get_16 (&wrtarget
, pb_data
+ 4, len_data
- 4);
1268 cg
->bits
= windres_get_16 (&wrtarget
, pb_data
+ 6, len_data
- 6);
1269 cg
->bytes
= windres_get_32 (&wrtarget
, pb_data
+ 8, len_data
- 8);
1270 cg
->index
= windres_get_16 (&wrtarget
, pb_data
+ 12, len_data
- 12);
1280 r
= define_standard_resource (&resources
, RT_GROUP_ICON
, id
,
1281 resinfo
->language
, 0);
1282 r
->type
= RES_TYPE_GROUP_ICON
;
1283 r
->u
.group_icon
= first
;
1284 r
->res_info
= *resinfo
;
1288 define_group_cursor_rcdata (rc_res_id id
, const rc_res_res_info
*resinfo
,
1289 rc_rcdata_item
*data
)
1292 rc_group_cursor
*cg
, *first
, *cur
;
1293 rc_uint_type len_data
;
1296 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
1300 while (len_data
>= 6)
1303 unsigned short type
;
1304 type
= windres_get_16 (&wrtarget
, pb_data
+ 2, len_data
- 2);
1306 fatal (_("unexpected group cursor type %d"), type
);
1307 c
= windres_get_16 (&wrtarget
, pb_data
+ 4, len_data
- 4);
1311 for (i
= 0; i
< c
; i
++)
1314 fatal ("too small group icon rcdata");
1315 cg
= (rc_group_cursor
*) res_alloc (sizeof (rc_group_cursor
));
1317 cg
->width
= windres_get_16 (&wrtarget
, pb_data
, len_data
);
1318 cg
->height
= windres_get_16 (&wrtarget
, pb_data
+ 2, len_data
- 2);
1319 cg
->planes
= windres_get_16 (&wrtarget
, pb_data
+ 4, len_data
- 4);
1320 cg
->bits
= windres_get_16 (&wrtarget
, pb_data
+ 6, len_data
- 6);
1321 cg
->bytes
= windres_get_32 (&wrtarget
, pb_data
+ 8, len_data
- 8);
1322 cg
->index
= windres_get_16 (&wrtarget
, pb_data
+ 12, len_data
- 12);
1333 r
= define_standard_resource (&resources
, RT_GROUP_ICON
, id
,
1334 resinfo
->language
, 0);
1335 r
->type
= RES_TYPE_GROUP_CURSOR
;
1336 r
->u
.group_cursor
= first
;
1337 r
->res_info
= *resinfo
;
1341 define_cursor_rcdata (rc_res_id id
, const rc_res_res_info
*resinfo
,
1342 rc_rcdata_item
*data
)
1346 rc_uint_type len_data
;
1349 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
1351 c
= (rc_cursor
*) res_alloc (sizeof (rc_cursor
));
1352 c
->xhotspot
= windres_get_16 (&wrtarget
, pb_data
, len_data
);
1353 c
->yhotspot
= windres_get_16 (&wrtarget
, pb_data
+ 2, len_data
- 2);
1354 c
->length
= len_data
- BIN_CURSOR_SIZE
;
1355 c
->data
= (const bfd_byte
*) (data
+ BIN_CURSOR_SIZE
);
1357 r
= define_standard_resource (&resources
, RT_CURSOR
, id
, resinfo
->language
, 0);
1358 r
->type
= RES_TYPE_CURSOR
;
1360 r
->res_info
= *resinfo
;
1364 define_bitmap_rcdata (rc_res_id id
, const rc_res_res_info
*resinfo
,
1365 rc_rcdata_item
*data
)
1368 rc_uint_type len_data
;
1371 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
1373 r
= define_standard_resource (&resources
, RT_BITMAP
, id
, resinfo
->language
, 0);
1374 r
->type
= RES_TYPE_BITMAP
;
1375 r
->u
.data
.length
= len_data
;
1376 r
->u
.data
.data
= pb_data
;
1377 r
->res_info
= *resinfo
;
1381 define_icon_rcdata (rc_res_id id
, const rc_res_res_info
*resinfo
,
1382 rc_rcdata_item
*data
)
1385 rc_uint_type len_data
;
1388 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
1390 r
= define_standard_resource (&resources
, RT_ICON
, id
, resinfo
->language
, 0);
1391 r
->type
= RES_TYPE_ICON
;
1392 r
->u
.data
.length
= len_data
;
1393 r
->u
.data
.data
= pb_data
;
1394 r
->res_info
= *resinfo
;
1397 /* Define a menu resource. */
1400 define_menu (rc_res_id id
, const rc_res_res_info
*resinfo
,
1401 rc_menuitem
*menuitems
)
1406 m
= (rc_menu
*) res_alloc (sizeof (rc_menu
));
1407 m
->items
= menuitems
;
1410 r
= define_standard_resource (&resources
, RT_MENU
, id
, resinfo
->language
, 0);
1411 r
->type
= RES_TYPE_MENU
;
1413 r
->res_info
= *resinfo
;
1416 /* Define a menu item. This does not define a resource, but merely
1417 allocates and fills in a structure. */
1420 define_menuitem (const unichar
*text
, rc_uint_type menuid
, rc_uint_type type
,
1421 rc_uint_type state
, rc_uint_type help
,
1422 rc_menuitem
*menuitems
)
1426 mi
= (rc_menuitem
*) res_alloc (sizeof (rc_menuitem
));
1431 mi
->text
= unichar_dup (text
);
1433 mi
->popup
= menuitems
;
1437 /* Define a messagetable resource. */
1440 define_messagetable (rc_res_id id
, const rc_res_res_info
*resinfo
,
1441 const char *filename
)
1444 char *real_filename
;
1449 e
= open_file_search (filename
, FOPEN_RB
, "messagetable file",
1452 if (stat (real_filename
, &s
) < 0)
1453 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
1456 data
= (bfd_byte
*) res_alloc (s
.st_size
);
1458 get_data (e
, data
, s
.st_size
, real_filename
);
1461 free (real_filename
);
1463 r
= define_standard_resource (&resources
, RT_MESSAGETABLE
, id
,
1464 resinfo
->language
, 0);
1466 r
->type
= RES_TYPE_MESSAGETABLE
;
1467 r
->u
.data
.length
= s
.st_size
;
1468 r
->u
.data
.data
= data
;
1469 r
->res_info
= *resinfo
;
1472 /* Define an rcdata resource. */
1475 define_rcdata (rc_res_id id
, const rc_res_res_info
*resinfo
,
1476 rc_rcdata_item
*data
)
1480 r
= define_standard_resource (&resources
, RT_RCDATA
, id
,
1481 resinfo
->language
, 0);
1482 r
->type
= RES_TYPE_RCDATA
;
1484 r
->res_info
= *resinfo
;
1487 /* Create an rcdata item holding a string. */
1490 define_rcdata_string (const char *string
, rc_uint_type len
)
1495 ri
= (rc_rcdata_item
*) res_alloc (sizeof (rc_rcdata_item
));
1497 ri
->type
= RCDATA_STRING
;
1498 ri
->u
.string
.length
= len
;
1499 s
= (char *) res_alloc (len
);
1500 memcpy (s
, string
, len
);
1506 /* Create an rcdata item holding a unicode string. */
1509 define_rcdata_unistring (const unichar
*string
, rc_uint_type len
)
1514 ri
= (rc_rcdata_item
*) res_alloc (sizeof (rc_rcdata_item
));
1516 ri
->type
= RCDATA_WSTRING
;
1517 ri
->u
.wstring
.length
= len
;
1518 s
= (unichar
*) res_alloc (len
* sizeof (unichar
));
1519 memcpy (s
, string
, len
* sizeof (unichar
));
1520 ri
->u
.wstring
.w
= s
;
1525 /* Create an rcdata item holding a number. */
1528 define_rcdata_number (rc_uint_type val
, int dword
)
1532 ri
= (rc_rcdata_item
*) res_alloc (sizeof (rc_rcdata_item
));
1534 ri
->type
= dword
? RCDATA_DWORD
: RCDATA_WORD
;
1540 /* Define a stringtable resource. This is called for each string
1541 which appears in a STRINGTABLE statement. */
1544 define_stringtable (const rc_res_res_info
*resinfo
,
1545 rc_uint_type stringid
, const unichar
*string
)
1551 id
.u
.id
= (stringid
>> 4) + 1;
1552 r
= define_standard_resource (&resources
, RT_STRING
, id
,
1553 resinfo
->language
, 1);
1555 if (r
->type
== RES_TYPE_UNINITIALIZED
)
1559 r
->type
= RES_TYPE_STRINGTABLE
;
1560 r
->u
.stringtable
= ((rc_stringtable
*)
1561 res_alloc (sizeof (rc_stringtable
)));
1562 for (i
= 0; i
< 16; i
++)
1564 r
->u
.stringtable
->strings
[i
].length
= 0;
1565 r
->u
.stringtable
->strings
[i
].string
= NULL
;
1568 r
->res_info
= *resinfo
;
1571 r
->u
.stringtable
->strings
[stringid
& 0xf].length
= unichar_len (string
);
1572 r
->u
.stringtable
->strings
[stringid
& 0xf].string
= unichar_dup (string
);
1576 define_toolbar (rc_res_id id
, rc_res_res_info
*resinfo
, rc_uint_type width
, rc_uint_type height
,
1577 rc_toolbar_item
*items
)
1582 t
= (rc_toolbar
*) res_alloc (sizeof (rc_toolbar
));
1583 t
->button_width
= width
;
1584 t
->button_height
= height
;
1587 while (items
!= NULL
)
1590 items
= items
->next
;
1592 r
= define_standard_resource (&resources
, RT_TOOLBAR
, id
, resinfo
->language
, 0);
1593 r
->type
= RES_TYPE_TOOLBAR
;
1595 r
->res_info
= *resinfo
;
1598 /* Define a user data resource where the data is in the rc file. */
1601 define_user_data (rc_res_id id
, rc_res_id type
,
1602 const rc_res_res_info
*resinfo
,
1603 rc_rcdata_item
*data
)
1608 rc_uint_type len_data
;
1610 /* We have to check if the binary data is parsed specially. */
1611 if (type
.named
== 0)
1616 define_fontdir_rcdata (id
, resinfo
, data
);
1619 define_font_rcdata (id
, resinfo
, data
);
1622 define_icon_rcdata (id
, resinfo
, data
);
1625 define_bitmap_rcdata (id
, resinfo
, data
);
1628 define_cursor_rcdata (id
, resinfo
, data
);
1631 define_group_icon_rcdata (id
, resinfo
, data
);
1633 case RT_GROUP_CURSOR
:
1634 define_group_cursor_rcdata (id
, resinfo
, data
);
1636 case RT_MESSAGETABLE
:
1637 define_messagetable_rcdata (id
, resinfo
, data
);
1640 /* Treat as normal user-data. */
1647 ids
[2].u
.id
= resinfo
->language
;
1649 r
= define_resource (& resources
, 3, ids
, 0);
1650 r
->type
= RES_TYPE_USERDATA
;
1651 r
->u
.userdata
= ((rc_rcdata_item
*)
1652 res_alloc (sizeof (rc_rcdata_item
)));
1653 r
->u
.userdata
->next
= NULL
;
1654 r
->u
.userdata
->type
= RCDATA_BUFFER
;
1655 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
1656 r
->u
.userdata
->u
.buffer
.length
= len_data
;
1657 r
->u
.userdata
->u
.buffer
.data
= pb_data
;
1658 r
->res_info
= *resinfo
;
1662 define_rcdata_file (rc_res_id id
, const rc_res_res_info
*resinfo
,
1663 const char *filename
)
1667 char *real_filename
;
1671 e
= open_file_search (filename
, FOPEN_RB
, "file", &real_filename
);
1674 if (stat (real_filename
, &s
) < 0)
1675 fatal (_("stat failed on file `%s': %s"), real_filename
,
1678 data
= (bfd_byte
*) res_alloc (s
.st_size
);
1680 get_data (e
, data
, s
.st_size
, real_filename
);
1683 free (real_filename
);
1685 ri
= (rc_rcdata_item
*) res_alloc (sizeof (rc_rcdata_item
));
1687 ri
->type
= RCDATA_BUFFER
;
1688 ri
->u
.buffer
.length
= s
.st_size
;
1689 ri
->u
.buffer
.data
= data
;
1691 define_rcdata (id
, resinfo
, ri
);
1694 /* Define a user data resource where the data is in a file. */
1697 define_user_file (rc_res_id id
, rc_res_id type
,
1698 const rc_res_res_info
*resinfo
, const char *filename
)
1701 char *real_filename
;
1707 e
= open_file_search (filename
, FOPEN_RB
, "file", &real_filename
);
1709 if (stat (real_filename
, &s
) < 0)
1710 fatal (_("stat failed on file `%s': %s"), real_filename
,
1713 data
= (bfd_byte
*) res_alloc (s
.st_size
);
1715 get_data (e
, data
, s
.st_size
, real_filename
);
1718 free (real_filename
);
1723 ids
[2].u
.id
= resinfo
->language
;
1725 r
= define_resource (&resources
, 3, ids
, 0);
1726 r
->type
= RES_TYPE_USERDATA
;
1727 r
->u
.userdata
= ((rc_rcdata_item
*)
1728 res_alloc (sizeof (rc_rcdata_item
)));
1729 r
->u
.userdata
->next
= NULL
;
1730 r
->u
.userdata
->type
= RCDATA_BUFFER
;
1731 r
->u
.userdata
->u
.buffer
.length
= s
.st_size
;
1732 r
->u
.userdata
->u
.buffer
.data
= data
;
1733 r
->res_info
= *resinfo
;
1736 /* Define a versioninfo resource. */
1739 define_versioninfo (rc_res_id id
, rc_uint_type language
,
1740 rc_fixed_versioninfo
*fixedverinfo
,
1741 rc_ver_info
*verinfo
)
1745 r
= define_standard_resource (&resources
, RT_VERSION
, id
, language
, 0);
1746 r
->type
= RES_TYPE_VERSIONINFO
;
1747 r
->u
.versioninfo
= ((rc_versioninfo
*)
1748 res_alloc (sizeof (rc_versioninfo
)));
1749 r
->u
.versioninfo
->fixed
= fixedverinfo
;
1750 r
->u
.versioninfo
->var
= verinfo
;
1751 r
->res_info
.language
= language
;
1754 /* Add string version info to a list of version information. */
1757 append_ver_stringfileinfo (rc_ver_info
*verinfo
, const char *language
,
1758 rc_ver_stringinfo
*strings
)
1760 rc_ver_info
*vi
, **pp
;
1762 vi
= (rc_ver_info
*) res_alloc (sizeof (rc_ver_info
));
1764 vi
->type
= VERINFO_STRING
;
1765 unicode_from_ascii ((rc_uint_type
*) NULL
, &vi
->u
.string
.language
, language
);
1766 vi
->u
.string
.strings
= strings
;
1768 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1775 /* Add variable version info to a list of version information. */
1778 append_ver_varfileinfo (rc_ver_info
*verinfo
, const unichar
*key
,
1779 rc_ver_varinfo
*var
)
1781 rc_ver_info
*vi
, **pp
;
1783 vi
= (rc_ver_info
*) res_alloc (sizeof *vi
);
1785 vi
->type
= VERINFO_VAR
;
1786 vi
->u
.var
.key
= unichar_dup (key
);
1787 vi
->u
.var
.var
= var
;
1789 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1796 /* Append version string information to a list. */
1799 append_verval (rc_ver_stringinfo
*strings
, const unichar
*key
,
1800 const unichar
*value
)
1802 rc_ver_stringinfo
*vs
, **pp
;
1804 vs
= (rc_ver_stringinfo
*) res_alloc (sizeof (rc_ver_stringinfo
));
1806 vs
->key
= unichar_dup (key
);
1807 vs
->value
= unichar_dup (value
);
1809 for (pp
= &strings
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1816 /* Append version variable information to a list. */
1819 append_vertrans (rc_ver_varinfo
*var
, rc_uint_type language
,
1820 rc_uint_type charset
)
1822 rc_ver_varinfo
*vv
, **pp
;
1824 vv
= (rc_ver_varinfo
*) res_alloc (sizeof (rc_ver_varinfo
));
1826 vv
->language
= language
;
1827 vv
->charset
= charset
;
1829 for (pp
= &var
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1836 /* Local functions used to write out an rc file. */
1838 static void indent (FILE *, int);
1839 static void write_rc_directory (FILE *, const rc_res_directory
*, const rc_res_id
*,
1840 const rc_res_id
*, rc_uint_type
*, int);
1841 static void write_rc_subdir (FILE *, const rc_res_entry
*, const rc_res_id
*,
1842 const rc_res_id
*, rc_uint_type
*, int);
1843 static void write_rc_resource (FILE *, const rc_res_id
*, const rc_res_id
*,
1844 const rc_res_resource
*, rc_uint_type
*);
1845 static void write_rc_accelerators (FILE *, const rc_accelerator
*);
1846 static void write_rc_cursor (FILE *, const rc_cursor
*);
1847 static void write_rc_group_cursor (FILE *, const rc_group_cursor
*);
1848 static void write_rc_dialog (FILE *, const rc_dialog
*);
1849 static void write_rc_dialog_control (FILE *, const rc_dialog_control
*);
1850 static void write_rc_fontdir (FILE *, const rc_fontdir
*);
1851 static void write_rc_group_icon (FILE *, const rc_group_icon
*);
1852 static void write_rc_menu (FILE *, const rc_menu
*, int);
1853 static void write_rc_toolbar (FILE *, const rc_toolbar
*);
1854 static void write_rc_menuitems (FILE *, const rc_menuitem
*, int, int);
1855 static void write_rc_messagetable (FILE *, rc_uint_type
, const bfd_byte
*);
1857 static void write_rc_datablock (FILE *, rc_uint_type
, const bfd_byte
*, int, int, int);
1858 static void write_rc_rcdata (FILE *, const rc_rcdata_item
*, int);
1859 static void write_rc_stringtable (FILE *, const rc_res_id
*, const rc_stringtable
*);
1860 static void write_rc_versioninfo (FILE *, const rc_versioninfo
*);
1862 /* Indent a given number of spaces. */
1865 indent (FILE *e
, int c
)
1869 for (i
= 0; i
< c
; i
++)
1873 /* Dump the resources we have read in the format of an rc file.
1875 Reasoned by the fact, that some resources need to be stored into file and
1876 refer to that file, we use the user-data model for that to express it binary
1877 without the need to store it somewhere externally. */
1880 write_rc_file (const char *filename
, const rc_res_directory
*resources
)
1883 rc_uint_type language
;
1885 if (filename
== NULL
)
1889 e
= fopen (filename
, FOPEN_WT
);
1891 fatal (_("can't open `%s' for output: %s"), filename
, strerror (errno
));
1894 language
= (rc_uint_type
) ((bfd_signed_vma
) -1);
1895 write_rc_directory (e
, resources
, (const rc_res_id
*) NULL
,
1896 (const rc_res_id
*) NULL
, &language
, 1);
1899 /* Write out a directory. E is the file to write to. RD is the
1900 directory. TYPE is a pointer to the level 1 ID which serves as the
1901 resource type. NAME is a pointer to the level 2 ID which serves as
1902 an individual resource name. LANGUAGE is a pointer to the current
1903 language. LEVEL is the level in the tree. */
1906 write_rc_directory (FILE *e
, const rc_res_directory
*rd
,
1907 const rc_res_id
*type
, const rc_res_id
*name
,
1908 rc_uint_type
*language
, int level
)
1910 const rc_res_entry
*re
;
1912 /* Print out some COFF information that rc files can't represent. */
1913 if (rd
->time
!= 0 || rd
->characteristics
!= 0 || rd
->major
!= 0 || rd
->minor
!= 0)
1915 wr_printcomment (e
, "COFF information not part of RC");
1917 wr_printcomment (e
, "Time stamp: %u", rd
->time
);
1918 if (rd
->characteristics
!= 0)
1919 wr_printcomment (e
, "Characteristics: %u", rd
->characteristics
);
1920 if (rd
->major
!= 0 || rd
->minor
!= 0)
1921 wr_printcomment (e
, "Version major:%d minor:%d", rd
->major
, rd
->minor
);
1924 for (re
= rd
->entries
; re
!= NULL
; re
= re
->next
)
1929 /* If we're at level 1, the key of this resource is the
1930 type. This normally duplicates the information we have
1931 stored with the resource itself, but we need to remember
1932 the type if this is a user define resource type. */
1937 /* If we're at level 2, the key of this resource is the name
1938 we are going to use in the rc printout. */
1943 /* If we're at level 3, then this key represents a language.
1944 Use it to update the current language. */
1946 && re
->id
.u
.id
!= (unsigned long) (unsigned int) *language
1947 && (re
->id
.u
.id
& 0xffff) == re
->id
.u
.id
)
1949 wr_print (e
, "LANGUAGE %u, %u\n",
1950 re
->id
.u
.id
& ((1 << SUBLANG_SHIFT
) - 1),
1951 (re
->id
.u
.id
>> SUBLANG_SHIFT
) & 0xff);
1952 *language
= re
->id
.u
.id
;
1961 write_rc_subdir (e
, re
, type
, name
, language
, level
);
1966 /* This is the normal case: the three levels are
1967 TYPE/NAME/LANGUAGE. NAME will have been set at level
1968 2, and represents the name to use. We probably just
1969 set LANGUAGE, and it will probably match what the
1970 resource itself records if anything. */
1971 write_rc_resource (e
, type
, name
, re
->u
.res
, language
);
1975 wr_printcomment (e
, "Resource at unexpected level %d", level
);
1976 write_rc_resource (e
, type
, (rc_res_id
*) NULL
, re
->u
.res
,
1981 if (rd
->entries
== NULL
)
1987 /* Write out a subdirectory entry. E is the file to write to. RE is
1988 the subdirectory entry. TYPE and NAME are pointers to higher level
1989 IDs, or NULL. LANGUAGE is a pointer to the current language.
1990 LEVEL is the level in the tree. */
1993 write_rc_subdir (FILE *e
, const rc_res_entry
*re
,
1994 const rc_res_id
*type
, const rc_res_id
*name
,
1995 rc_uint_type
*language
, int level
)
2001 wr_printcomment (e
, "Type: ");
2003 res_id_print (e
, re
->id
, 1);
2008 switch (re
->id
.u
.id
)
2010 case RT_CURSOR
: s
= "cursor"; break;
2011 case RT_BITMAP
: s
= "bitmap"; break;
2012 case RT_ICON
: s
= "icon"; break;
2013 case RT_MENU
: s
= "menu"; break;
2014 case RT_DIALOG
: s
= "dialog"; break;
2015 case RT_STRING
: s
= "stringtable"; break;
2016 case RT_FONTDIR
: s
= "fontdir"; break;
2017 case RT_FONT
: s
= "font"; break;
2018 case RT_ACCELERATOR
: s
= "accelerators"; break;
2019 case RT_RCDATA
: s
= "rcdata"; break;
2020 case RT_MESSAGETABLE
: s
= "messagetable"; break;
2021 case RT_GROUP_CURSOR
: s
= "group cursor"; break;
2022 case RT_GROUP_ICON
: s
= "group icon"; break;
2023 case RT_VERSION
: s
= "version"; break;
2024 case RT_DLGINCLUDE
: s
= "dlginclude"; break;
2025 case RT_PLUGPLAY
: s
= "plugplay"; break;
2026 case RT_VXD
: s
= "vxd"; break;
2027 case RT_ANICURSOR
: s
= "anicursor"; break;
2028 case RT_ANIICON
: s
= "aniicon"; break;
2029 case RT_TOOLBAR
: s
= "toolbar"; break;
2030 case RT_HTML
: s
= "html"; break;
2031 default: s
= NULL
; break;
2035 fprintf (e
, "%s", s
);
2037 res_id_print (e
, re
->id
, 1);
2042 wr_printcomment (e
, "Name: ");
2043 res_id_print (e
, re
->id
, 1);
2047 wr_printcomment (e
, "Language: ");
2048 res_id_print (e
, re
->id
, 1);
2052 wr_printcomment (e
, "Level %d: ", level
);
2053 res_id_print (e
, re
->id
, 1);
2056 write_rc_directory (e
, re
->u
.dir
, type
, name
, language
, level
+ 1);
2059 /* Write out a single resource. E is the file to write to. TYPE is a
2060 pointer to the type of the resource. NAME is a pointer to the name
2061 of the resource; it will be NULL if there is a level mismatch. RES
2062 is the resource data. LANGUAGE is a pointer to the current
2066 write_rc_resource (FILE *e
, const rc_res_id
*type
,
2067 const rc_res_id
*name
, const rc_res_resource
*res
,
2068 rc_uint_type
*language
)
2079 case RES_TYPE_ACCELERATOR
:
2081 rt
= RT_ACCELERATOR
;
2084 case RES_TYPE_BITMAP
:
2085 s
= "2 /* RT_BITMAP */";
2089 case RES_TYPE_CURSOR
:
2090 s
= "1 /* RT_CURSOR */";
2094 case RES_TYPE_GROUP_CURSOR
:
2095 s
= "12 /* RT_GROUP_CURSOR */";
2096 rt
= RT_GROUP_CURSOR
;
2099 case RES_TYPE_DIALOG
:
2100 if (extended_dialog (res
->u
.dialog
))
2108 s
= "8 /* RT_FONT */";
2112 case RES_TYPE_FONTDIR
:
2113 s
= "7 /* RT_FONTDIR */";
2118 s
= "3 /* RT_ICON */";
2122 case RES_TYPE_GROUP_ICON
:
2123 s
= "14 /* RT_GROUP_ICON */";
2128 if (extended_menu (res
->u
.menu
))
2141 case RES_TYPE_MESSAGETABLE
:
2142 s
= "11 /* RT_MESSAGETABLE */";
2143 rt
= RT_MESSAGETABLE
;
2146 case RES_TYPE_RCDATA
:
2151 case RES_TYPE_STRINGTABLE
:
2156 case RES_TYPE_USERDATA
:
2161 case RES_TYPE_VERSIONINFO
:
2166 case RES_TYPE_TOOLBAR
:
2174 && (type
->named
|| type
->u
.id
!= (unsigned long) rt
))
2176 wr_printcomment (e
, "Unexpected resource type mismatch: ");
2177 res_id_print (e
, *type
, 1);
2178 fprintf (e
, " != %d", rt
);
2181 if (res
->coff_info
.codepage
!= 0)
2182 wr_printcomment (e
, "Code page: %u", res
->coff_info
.codepage
);
2183 if (res
->coff_info
.reserved
!= 0)
2184 wr_printcomment (e
, "COFF reserved value: %u", res
->coff_info
.reserved
);
2187 if (rt
== RT_STRING
)
2192 res_id_print (e
, *name
, 1);
2194 fprintf (e
, "??Unknown-Name??");
2199 fprintf (e
, "%s", s
);
2200 else if (type
!= NULL
)
2202 if (type
->named
== 0)
2204 #define PRINT_RT_NAME(NAME) case NAME: \
2205 fprintf (e, "%u /* %s */", (unsigned int) NAME, #NAME); \
2211 res_id_print (e
, *type
, 0);
2214 PRINT_RT_NAME(RT_MANIFEST
);
2215 PRINT_RT_NAME(RT_ANICURSOR
);
2216 PRINT_RT_NAME(RT_ANIICON
);
2217 PRINT_RT_NAME(RT_RCDATA
);
2218 PRINT_RT_NAME(RT_ICON
);
2219 PRINT_RT_NAME(RT_CURSOR
);
2220 PRINT_RT_NAME(RT_BITMAP
);
2221 PRINT_RT_NAME(RT_PLUGPLAY
);
2222 PRINT_RT_NAME(RT_VXD
);
2223 PRINT_RT_NAME(RT_FONT
);
2224 PRINT_RT_NAME(RT_FONTDIR
);
2225 PRINT_RT_NAME(RT_HTML
);
2226 PRINT_RT_NAME(RT_MESSAGETABLE
);
2227 PRINT_RT_NAME(RT_DLGINCLUDE
);
2228 PRINT_RT_NAME(RT_DLGINIT
);
2230 #undef PRINT_RT_NAME
2233 res_id_print (e
, *type
, 1);
2236 fprintf (e
, "??Unknown-Type??");
2238 if (res
->res_info
.memflags
!= 0)
2240 if ((res
->res_info
.memflags
& MEMFLAG_MOVEABLE
) != 0)
2241 fprintf (e
, " MOVEABLE");
2242 if ((res
->res_info
.memflags
& MEMFLAG_PURE
) != 0)
2243 fprintf (e
, " PURE");
2244 if ((res
->res_info
.memflags
& MEMFLAG_PRELOAD
) != 0)
2245 fprintf (e
, " PRELOAD");
2246 if ((res
->res_info
.memflags
& MEMFLAG_DISCARDABLE
) != 0)
2247 fprintf (e
, " DISCARDABLE");
2250 if (res
->type
== RES_TYPE_DIALOG
)
2252 fprintf (e
, " %d, %d, %d, %d",
2253 (int) res
->u
.dialog
->x
, (int) res
->u
.dialog
->y
,
2254 (int) res
->u
.dialog
->width
, (int) res
->u
.dialog
->height
);
2255 if (res
->u
.dialog
->ex
!= NULL
2256 && res
->u
.dialog
->ex
->help
!= 0)
2257 fprintf (e
, ", %u", (unsigned int) res
->u
.dialog
->ex
->help
);
2259 else if (res
->type
== RES_TYPE_TOOLBAR
)
2261 fprintf (e
, " %d, %d", (int) res
->u
.toolbar
->button_width
,
2262 (int) res
->u
.toolbar
->button_height
);
2267 if ((res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
2268 || res
->res_info
.characteristics
!= 0
2269 || res
->res_info
.version
!= 0)
2275 case RES_TYPE_ACCELERATOR
:
2276 case RES_TYPE_DIALOG
:
2278 case RES_TYPE_RCDATA
:
2279 case RES_TYPE_STRINGTABLE
:
2288 if (res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
2289 fprintf (e
, "%sLANGUAGE %d, %d\n",
2290 modifiers
? "// " : "",
2291 (int) res
->res_info
.language
& ((1<<SUBLANG_SHIFT
)-1),
2292 (int) (res
->res_info
.language
>> SUBLANG_SHIFT
) & 0xff);
2293 if (res
->res_info
.characteristics
!= 0)
2294 fprintf (e
, "%sCHARACTERISTICS %u\n",
2295 modifiers
? "// " : "",
2296 (unsigned int) res
->res_info
.characteristics
);
2297 if (res
->res_info
.version
!= 0)
2298 fprintf (e
, "%sVERSION %u\n",
2299 modifiers
? "// " : "",
2300 (unsigned int) res
->res_info
.version
);
2308 case RES_TYPE_ACCELERATOR
:
2309 write_rc_accelerators (e
, res
->u
.acc
);
2312 case RES_TYPE_CURSOR
:
2313 write_rc_cursor (e
, res
->u
.cursor
);
2316 case RES_TYPE_GROUP_CURSOR
:
2317 write_rc_group_cursor (e
, res
->u
.group_cursor
);
2320 case RES_TYPE_DIALOG
:
2321 write_rc_dialog (e
, res
->u
.dialog
);
2324 case RES_TYPE_FONTDIR
:
2325 write_rc_fontdir (e
, res
->u
.fontdir
);
2328 case RES_TYPE_GROUP_ICON
:
2329 write_rc_group_icon (e
, res
->u
.group_icon
);
2333 write_rc_menu (e
, res
->u
.menu
, menuex
);
2336 case RES_TYPE_RCDATA
:
2337 write_rc_rcdata (e
, res
->u
.rcdata
, 0);
2340 case RES_TYPE_STRINGTABLE
:
2341 write_rc_stringtable (e
, name
, res
->u
.stringtable
);
2344 case RES_TYPE_USERDATA
:
2345 write_rc_rcdata (e
, res
->u
.userdata
, 0);
2348 case RES_TYPE_TOOLBAR
:
2349 write_rc_toolbar (e
, res
->u
.toolbar
);
2352 case RES_TYPE_VERSIONINFO
:
2353 write_rc_versioninfo (e
, res
->u
.versioninfo
);
2356 case RES_TYPE_BITMAP
:
2359 write_rc_datablock (e
, res
->u
.data
.length
, res
->u
.data
.data
, 0, 1, 0);
2361 case RES_TYPE_MESSAGETABLE
:
2362 write_rc_messagetable (e
, res
->u
.data
.length
, res
->u
.data
.data
);
2367 /* Write out accelerator information. */
2370 write_rc_accelerators (FILE *e
, const rc_accelerator
*accelerators
)
2372 const rc_accelerator
*acc
;
2374 fprintf (e
, "BEGIN\n");
2375 for (acc
= accelerators
; acc
!= NULL
; acc
= acc
->next
)
2381 if ((acc
->key
& 0x7f) == acc
->key
2382 && ISPRINT (acc
->key
)
2383 && (acc
->flags
& ACC_VIRTKEY
) == 0)
2385 fprintf (e
, "\"%c\"", (char) acc
->key
);
2390 fprintf (e
, "%d", (int) acc
->key
);
2394 fprintf (e
, ", %d", (int) acc
->id
);
2398 if ((acc
->flags
& ACC_VIRTKEY
) != 0)
2399 fprintf (e
, ", VIRTKEY");
2401 fprintf (e
, ", ASCII");
2404 if ((acc
->flags
& ACC_SHIFT
) != 0)
2405 fprintf (e
, ", SHIFT");
2406 if ((acc
->flags
& ACC_CONTROL
) != 0)
2407 fprintf (e
, ", CONTROL");
2408 if ((acc
->flags
& ACC_ALT
) != 0)
2409 fprintf (e
, ", ALT");
2414 fprintf (e
, "END\n");
2417 /* Write out cursor information. This would normally be in a separate
2418 file, which the rc file would include. */
2421 write_rc_cursor (FILE *e
, const rc_cursor
*cursor
)
2423 fprintf (e
, "BEGIN\n");
2425 fprintf (e
, " 0x%x, 0x%x,\t/* Hotspot x: %d, y: %d. */\n",
2426 (unsigned int) cursor
->xhotspot
, (unsigned int) cursor
->yhotspot
,
2427 (int) cursor
->xhotspot
, (int) cursor
->yhotspot
);
2428 write_rc_datablock (e
, (rc_uint_type
) cursor
->length
, (const bfd_byte
*) cursor
->data
,
2430 fprintf (e
, "END\n");
2433 /* Write out group cursor data. This would normally be built from the
2437 write_rc_group_cursor (FILE *e
, const rc_group_cursor
*group_cursor
)
2439 const rc_group_cursor
*gc
;
2442 for (c
= 0, gc
= group_cursor
; gc
!= NULL
; gc
= gc
->next
, c
++)
2444 fprintf (e
, "BEGIN\n");
2447 fprintf (e
, "0, 2, %d%s\t /* Having %d items. */\n", c
, (c
!= 0 ? "," : ""), c
);
2449 fprintf (e
, "/* width, height, planes, bits, bytes, index. */\n");
2451 for (c
= 1, gc
= group_cursor
; gc
!= NULL
; gc
= gc
->next
, c
++)
2454 fprintf (e
, "%d, %d, %d, %d, 0x%xL, %d%s /* Element %d. */\n",
2455 (int) gc
->width
, (int) gc
->height
, (int) gc
->planes
, (int) gc
->bits
,
2456 (unsigned int) gc
->bytes
, (int) gc
->index
, (gc
->next
!= NULL
? "," : ""), c
);
2457 fprintf (e
, "/* width: %d; height %d; planes %d; bits %d. */\n",
2458 (int) gc
->width
, (int) gc
->height
, (int) gc
->planes
,
2461 fprintf (e
, "END\n");
2464 /* Write dialog data. */
2467 write_rc_dialog (FILE *e
, const rc_dialog
*dialog
)
2469 const rc_dialog_control
*control
;
2471 fprintf (e
, "STYLE 0x%x\n", dialog
->style
);
2473 if (dialog
->exstyle
!= 0)
2474 fprintf (e
, "EXSTYLE 0x%x\n", (unsigned int) dialog
->exstyle
);
2476 if ((dialog
->class.named
&& dialog
->class.u
.n
.length
> 0)
2477 || dialog
->class.u
.id
!= 0)
2479 fprintf (e
, "CLASS ");
2480 res_id_print (e
, dialog
->class, 1);
2484 if (dialog
->caption
!= NULL
)
2486 fprintf (e
, "CAPTION ");
2487 unicode_print_quoted (e
, dialog
->caption
, -1);
2491 if ((dialog
->menu
.named
&& dialog
->menu
.u
.n
.length
> 0)
2492 || dialog
->menu
.u
.id
!= 0)
2494 fprintf (e
, "MENU ");
2495 res_id_print (e
, dialog
->menu
, 0);
2499 if (dialog
->font
!= NULL
)
2501 fprintf (e
, "FONT %d, ", (int) dialog
->pointsize
);
2502 unicode_print_quoted (e
, dialog
->font
, -1);
2503 if (dialog
->ex
!= NULL
2504 && (dialog
->ex
->weight
!= 0
2505 || dialog
->ex
->italic
!= 0
2506 || dialog
->ex
->charset
!= 1))
2507 fprintf (e
, ", %d, %d, %d",
2508 (int) dialog
->ex
->weight
,
2509 (int) dialog
->ex
->italic
,
2510 (int) dialog
->ex
->charset
);
2514 fprintf (e
, "BEGIN\n");
2516 for (control
= dialog
->controls
; control
!= NULL
; control
= control
->next
)
2517 write_rc_dialog_control (e
, control
);
2519 fprintf (e
, "END\n");
2522 /* For each predefined control keyword, this table provides the class
2528 unsigned short class;
2529 unsigned long style
;
2532 static const struct control_info control_info
[] =
2534 { "AUTO3STATE", CTL_BUTTON
, BS_AUTO3STATE
},
2535 { "AUTOCHECKBOX", CTL_BUTTON
, BS_AUTOCHECKBOX
},
2536 { "AUTORADIOBUTTON", CTL_BUTTON
, BS_AUTORADIOBUTTON
},
2537 { "CHECKBOX", CTL_BUTTON
, BS_CHECKBOX
},
2538 { "COMBOBOX", CTL_COMBOBOX
, (unsigned long) -1 },
2539 { "CTEXT", CTL_STATIC
, SS_CENTER
},
2540 { "DEFPUSHBUTTON", CTL_BUTTON
, BS_DEFPUSHBUTTON
},
2541 { "EDITTEXT", CTL_EDIT
, (unsigned long) -1 },
2542 { "GROUPBOX", CTL_BUTTON
, BS_GROUPBOX
},
2543 { "ICON", CTL_STATIC
, SS_ICON
},
2544 { "LISTBOX", CTL_LISTBOX
, (unsigned long) -1 },
2545 { "LTEXT", CTL_STATIC
, SS_LEFT
},
2546 { "PUSHBOX", CTL_BUTTON
, BS_PUSHBOX
},
2547 { "PUSHBUTTON", CTL_BUTTON
, BS_PUSHBUTTON
},
2548 { "RADIOBUTTON", CTL_BUTTON
, BS_RADIOBUTTON
},
2549 { "RTEXT", CTL_STATIC
, SS_RIGHT
},
2550 { "SCROLLBAR", CTL_SCROLLBAR
, (unsigned long) -1 },
2551 { "STATE3", CTL_BUTTON
, BS_3STATE
},
2552 /* It's important that USERBUTTON come after all the other button
2553 types, so that it won't be matched too early. */
2554 { "USERBUTTON", CTL_BUTTON
, (unsigned long) -1 },
2558 /* Write a dialog control. */
2561 write_rc_dialog_control (FILE *e
, const rc_dialog_control
*control
)
2563 const struct control_info
*ci
;
2567 if (control
->class.named
)
2571 for (ci
= control_info
; ci
->name
!= NULL
; ++ci
)
2572 if (ci
->class == control
->class.u
.id
2573 && (ci
->style
== (unsigned long) -1
2574 || ci
->style
== (control
->style
& 0xff)))
2578 fprintf (e
, "CONTROL");
2579 else if (ci
->name
!= NULL
)
2580 fprintf (e
, "%s", ci
->name
);
2583 fprintf (e
, "CONTROL");
2587 if (control
->text
.named
|| control
->text
.u
.id
!= 0)
2590 res_id_print (e
, control
->text
, 1);
2594 fprintf (e
, " %d, ", (int) control
->id
);
2598 if (control
->class.named
)
2600 res_id_print (e
, control
->class, 0);
2601 if (control
->class.named
)
2603 fprintf (e
, ", 0x%x, ", (unsigned int) control
->style
);
2606 fprintf (e
, "%d, %d", (int) control
->x
, (int) control
->y
);
2608 if (control
->style
!= SS_ICON
2609 || control
->exstyle
!= 0
2610 || control
->width
!= 0
2611 || control
->height
!= 0
2612 || control
->help
!= 0)
2614 fprintf (e
, ", %d, %d", (int) control
->width
, (int) control
->height
);
2616 /* FIXME: We don't need to print the style if it is the default.
2617 More importantly, in certain cases we actually need to turn
2618 off parts of the forced style, by using NOT. */
2620 fprintf (e
, ", 0x%x", (unsigned int) control
->style
);
2622 if (control
->exstyle
!= 0 || control
->help
!= 0)
2623 fprintf (e
, ", 0x%x, %u", (unsigned int) control
->exstyle
,
2624 (unsigned int) control
->help
);
2629 if (control
->data
!= NULL
)
2630 write_rc_rcdata (e
, control
->data
, 2);
2633 /* Write out font directory data. This would normally be built from
2637 write_rc_fontdir (FILE *e
, const rc_fontdir
*fontdir
)
2639 const rc_fontdir
*fc
;
2642 for (c
= 0, fc
= fontdir
; fc
!= NULL
; fc
= fc
->next
, c
++)
2644 fprintf (e
, "BEGIN\n");
2646 fprintf (e
, "%d%s\t /* Has %d elements. */\n", c
, (c
!= 0 ? "," : ""), c
);
2647 for (c
= 1, fc
= fontdir
; fc
!= NULL
; fc
= fc
->next
, c
++)
2650 fprintf (e
, "%d,\t/* Font no %d with index %d. */\n",
2651 (int) fc
->index
, c
, (int) fc
->index
);
2652 write_rc_datablock (e
, (rc_uint_type
) fc
->length
- 2,
2653 (const bfd_byte
*) fc
->data
+ 4,fc
->next
!= NULL
,
2656 fprintf (e
, "END\n");
2659 /* Write out group icon data. This would normally be built from the
2663 write_rc_group_icon (FILE *e
, const rc_group_icon
*group_icon
)
2665 const rc_group_icon
*gi
;
2668 for (c
= 0, gi
= group_icon
; gi
!= NULL
; gi
= gi
->next
, c
++)
2671 fprintf (e
, "BEGIN\n");
2673 fprintf (e
, " 0, 1, %d%s\t /* Has %d elements. */\n", c
, (c
!= 0 ? "," : ""), c
);
2676 fprintf (e
, "/* \"width height colors pad\", planes, bits, bytes, index. */\n");
2677 for (c
= 1, gi
= group_icon
; gi
!= NULL
; gi
= gi
->next
, c
++)
2680 fprintf (e
, "\"\\%03o\\%03o\\%03o\\%03o\", %d, %d, 0x%xL, %d%s\t/* Element no %d. */\n",
2681 gi
->width
, gi
->height
, gi
->colors
, 0, (int) gi
->planes
, (int) gi
->bits
,
2682 (unsigned int) gi
->bytes
, (int) gi
->index
, (gi
->next
!= NULL
? "," : ""), c
);
2684 fprintf (e
, "END\n");
2687 /* Write out a menu resource. */
2690 write_rc_menu (FILE *e
, const rc_menu
*menu
, int menuex
)
2692 if (menu
->help
!= 0)
2693 fprintf (e
, "// Help ID: %u\n", (unsigned int) menu
->help
);
2694 write_rc_menuitems (e
, menu
->items
, menuex
, 0);
2698 write_rc_toolbar (FILE *e
, const rc_toolbar
*tb
)
2700 rc_toolbar_item
*it
;
2702 fprintf (e
, "BEGIN\n");
2707 if (it
->id
.u
.id
== 0)
2708 fprintf (e
, "SEPARATOR\n");
2710 fprintf (e
, "BUTTON %d\n", (int) it
->id
.u
.id
);
2714 fprintf (e
, "END\n");
2717 /* Write out menuitems. */
2720 write_rc_menuitems (FILE *e
, const rc_menuitem
*menuitems
, int menuex
,
2723 const rc_menuitem
*mi
;
2726 fprintf (e
, "BEGIN\n");
2728 for (mi
= menuitems
; mi
!= NULL
; mi
= mi
->next
)
2730 indent (e
, ind
+ 2);
2732 if (mi
->popup
== NULL
)
2733 fprintf (e
, "MENUITEM");
2735 fprintf (e
, "POPUP");
2738 && mi
->popup
== NULL
2743 fprintf (e
, " SEPARATOR\n");
2747 if (mi
->text
== NULL
)
2748 fprintf (e
, " \"\"");
2752 unicode_print_quoted (e
, mi
->text
, -1);
2757 if (mi
->popup
== NULL
)
2758 fprintf (e
, ", %d", (int) mi
->id
);
2760 if ((mi
->type
& MENUITEM_CHECKED
) != 0)
2761 fprintf (e
, ", CHECKED");
2762 if ((mi
->type
& MENUITEM_GRAYED
) != 0)
2763 fprintf (e
, ", GRAYED");
2764 if ((mi
->type
& MENUITEM_HELP
) != 0)
2765 fprintf (e
, ", HELP");
2766 if ((mi
->type
& MENUITEM_INACTIVE
) != 0)
2767 fprintf (e
, ", INACTIVE");
2768 if ((mi
->type
& MENUITEM_MENUBARBREAK
) != 0)
2769 fprintf (e
, ", MENUBARBREAK");
2770 if ((mi
->type
& MENUITEM_MENUBREAK
) != 0)
2771 fprintf (e
, ", MENUBREAK");
2775 if (mi
->id
!= 0 || mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2777 fprintf (e
, ", %d", (int) mi
->id
);
2778 if (mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2780 fprintf (e
, ", %u", (unsigned int) mi
->type
);
2781 if (mi
->state
!= 0 || mi
->help
!= 0)
2783 fprintf (e
, ", %u", (unsigned int) mi
->state
);
2785 fprintf (e
, ", %u", (unsigned int) mi
->help
);
2793 if (mi
->popup
!= NULL
)
2794 write_rc_menuitems (e
, mi
->popup
, menuex
, ind
+ 2);
2798 fprintf (e
, "END\n");
2802 test_rc_datablock_unicode (rc_uint_type length
, const bfd_byte
*data
)
2805 if ((length
& 1) != 0)
2808 for (i
= 0; i
< length
; i
+= 2)
2810 if (data
[i
] == 0 && data
[i
+ 1] == 0 && (i
+ 2) < length
)
2812 if (data
[i
] == 0xff && data
[i
+ 1] == 0xff)
2819 test_rc_datablock_text (rc_uint_type length
, const bfd_byte
*data
)
2829 for (i
= 0, c
= 0; i
< length
; i
++)
2831 if (! ISPRINT (data
[i
]) && data
[i
] != '\n'
2832 && ! (data
[i
] == '\r' && (i
+ 1) < length
&& data
[i
+ 1] == '\n')
2834 && ! (data
[i
] == 0 && (i
+ 1) != length
))
2840 else if (data
[i
] == '\n') has_nl
++;
2842 if (length
> 80 && ! has_nl
)
2844 c
= (((c
* 10000) + (i
/ 100) - 1)) / i
;
2851 write_rc_messagetable (FILE *e
, rc_uint_type length
, const bfd_byte
*data
)
2854 const struct bin_messagetable
*mt
;
2855 fprintf (e
, "BEGIN\n");
2857 write_rc_datablock (e
, length
, data
, 0, 0, 0);
2860 wr_printcomment (e
, "MC syntax dump");
2861 if (length
< BIN_MESSAGETABLE_SIZE
)
2866 mt
= (const struct bin_messagetable
*) data
;
2867 m
= windres_get_32 (&wrtarget
, mt
->cblocks
, length
);
2868 if (length
< (BIN_MESSAGETABLE_SIZE
+ m
* BIN_MESSAGETABLE_BLOCK_SIZE
))
2873 for (i
= 0; i
< m
; i
++)
2875 rc_uint_type low
, high
, offset
;
2876 const struct bin_messagetable_item
*mti
;
2878 low
= windres_get_32 (&wrtarget
, mt
->items
[i
].lowid
, 4);
2879 high
= windres_get_32 (&wrtarget
, mt
->items
[i
].highid
, 4);
2880 offset
= windres_get_32 (&wrtarget
, mt
->items
[i
].offset
, 4);
2883 rc_uint_type elen
, flags
;
2884 if ((offset
+ BIN_MESSAGETABLE_ITEM_SIZE
) > length
)
2889 mti
= (const struct bin_messagetable_item
*) &data
[offset
];
2890 elen
= windres_get_16 (&wrtarget
, mti
->length
, 2);
2891 flags
= windres_get_16 (&wrtarget
, mti
->flags
, 2);
2892 if ((offset
+ elen
) > length
)
2897 wr_printcomment (e
, "MessageId = 0x%x", low
);
2898 wr_printcomment (e
, "");
2899 if ((flags
& MESSAGE_RESOURCE_UNICODE
) == MESSAGE_RESOURCE_UNICODE
)
2900 unicode_print (e
, (const unichar
*) mti
->data
,
2901 (elen
- BIN_MESSAGETABLE_ITEM_SIZE
) / 2);
2903 ascii_print (e
, (const char *) mti
->data
,
2904 (elen
- BIN_MESSAGETABLE_ITEM_SIZE
));
2905 wr_printcomment (e
,"");
2912 wr_printcomment (e
, "Illegal data");
2914 fprintf (e
, "END\n");
2918 write_rc_datablock (FILE *e
, rc_uint_type length
, const bfd_byte
*data
, int has_next
,
2919 int hasblock
, int show_comment
)
2924 fprintf (e
, "BEGIN\n");
2926 if (show_comment
== -1)
2928 if (test_rc_datablock_text(length
, data
))
2931 for (i
= 0; i
< length
;)
2936 for (c
= 0; i
< length
&& c
< 160 && data
[i
] != '\n'; c
++, i
++)
2938 if (i
< length
&& data
[i
] == '\n')
2940 ascii_print (e
, (const char *) &data
[i
- c
], c
);
2949 fprintf (e
, "\"\"");
2955 fprintf (e
, "END\n");
2958 if (test_rc_datablock_unicode (length
, data
))
2961 for (i
= 0; i
< length
;)
2965 u
= (const unichar
*) &data
[i
];
2969 for (c
= 0; i
< length
&& c
< 160 && u
[c
] != '\n'; c
++, i
+= 2)
2971 if (i
< length
&& u
[c
] == '\n')
2973 unicode_print (e
, u
, c
);
2982 fprintf (e
, "L\"\"");
2988 fprintf (e
, "END\n");
2997 rc_uint_type i
, max_row
;
3000 max_row
= (show_comment
? 4 : 8);
3002 for (i
= 0; i
+ 3 < length
;)
3005 rc_uint_type comment_start
;
3012 for (k
= 0; k
< max_row
&& i
+ 3 < length
; k
++, i
+= 4)
3015 plen
= fprintf (e
, "0x%lxL",
3016 (long) windres_get_32 (&wrtarget
, data
+ i
, length
- i
));
3018 plen
= fprintf (e
, " 0x%lxL",
3019 (long) windres_get_32 (&wrtarget
, data
+ i
, length
- i
)) - 1;
3020 if (has_next
|| (i
+ 4) < length
)
3022 if (plen
>0 && plen
< 11)
3023 indent (e
, 11 - plen
);
3029 fprintf (e
, "\t/* ");
3030 ascii_print (e
, (const char *) &data
[comment_start
], i
- comment_start
);
3031 fprintf (e
, ". */");
3041 plen
= fprintf (e
, "0x%x",
3042 (int) windres_get_16 (&wrtarget
, data
+ i
, length
- i
));
3043 if (has_next
|| i
+ 2 < length
)
3045 if (plen
> 0 && plen
< 11)
3046 indent (e
, 11 - plen
);
3051 fprintf (e
, "\t/* ");
3052 ascii_print (e
, (const char *) &data
[i
], 2);
3053 fprintf (e
, ". */");
3065 ascii_print (e
, (const char *) &data
[i
], 1);
3074 fprintf (e
, "END\n");
3077 /* Write out an rcdata resource. This is also used for other types of
3078 resources that need to print arbitrary data. */
3081 write_rc_rcdata (FILE *e
, const rc_rcdata_item
*rcdata
, int ind
)
3083 const rc_rcdata_item
*ri
;
3086 fprintf (e
, "BEGIN\n");
3088 for (ri
= rcdata
; ri
!= NULL
; ri
= ri
->next
)
3090 if (ri
->type
== RCDATA_BUFFER
&& ri
->u
.buffer
.length
== 0)
3099 indent (e
, ind
+ 2);
3100 fprintf (e
, "%ld", (long) (ri
->u
.word
& 0xffff));
3104 indent (e
, ind
+ 2);
3105 fprintf (e
, "%luL", (unsigned long) ri
->u
.dword
);
3109 indent (e
, ind
+ 2);
3111 ascii_print (e
, ri
->u
.string
.s
, ri
->u
.string
.length
);
3115 case RCDATA_WSTRING
:
3116 indent (e
, ind
+ 2);
3118 unicode_print (e
, ri
->u
.wstring
.w
, ri
->u
.wstring
.length
);
3123 write_rc_datablock (e
, (rc_uint_type
) ri
->u
.buffer
.length
,
3124 (const bfd_byte
*) ri
->u
.buffer
.data
,
3125 ri
->next
!= NULL
, 0, -1);
3129 if (ri
->type
!= RCDATA_BUFFER
)
3131 if (ri
->next
!= NULL
)
3138 fprintf (e
, "END\n");
3141 /* Write out a stringtable resource. */
3144 write_rc_stringtable (FILE *e
, const rc_res_id
*name
,
3145 const rc_stringtable
*stringtable
)
3147 rc_uint_type offset
;
3150 if (name
!= NULL
&& ! name
->named
)
3151 offset
= (name
->u
.id
- 1) << 4;
3154 fprintf (e
, "/* %s string table name. */\n",
3155 name
== NULL
? "Missing" : "Invalid");
3159 fprintf (e
, "BEGIN\n");
3161 for (i
= 0; i
< 16; i
++)
3163 if (stringtable
->strings
[i
].length
!= 0)
3165 fprintf (e
, " %lu, ", (long) offset
+ i
);
3166 unicode_print_quoted (e
, stringtable
->strings
[i
].string
,
3167 stringtable
->strings
[i
].length
);
3172 fprintf (e
, "END\n");
3175 /* Write out a versioninfo resource. */
3178 write_rc_versioninfo (FILE *e
, const rc_versioninfo
*versioninfo
)
3180 const rc_fixed_versioninfo
*f
;
3181 const rc_ver_info
*vi
;
3183 f
= versioninfo
->fixed
;
3184 if (f
->file_version_ms
!= 0 || f
->file_version_ls
!= 0)
3185 fprintf (e
, " FILEVERSION %u, %u, %u, %u\n",
3186 (unsigned int) ((f
->file_version_ms
>> 16) & 0xffff),
3187 (unsigned int) (f
->file_version_ms
& 0xffff),
3188 (unsigned int) ((f
->file_version_ls
>> 16) & 0xffff),
3189 (unsigned int) (f
->file_version_ls
& 0xffff));
3190 if (f
->product_version_ms
!= 0 || f
->product_version_ls
!= 0)
3191 fprintf (e
, " PRODUCTVERSION %u, %u, %u, %u\n",
3192 (unsigned int) ((f
->product_version_ms
>> 16) & 0xffff),
3193 (unsigned int) (f
->product_version_ms
& 0xffff),
3194 (unsigned int) ((f
->product_version_ls
>> 16) & 0xffff),
3195 (unsigned int) (f
->product_version_ls
& 0xffff));
3196 if (f
->file_flags_mask
!= 0)
3197 fprintf (e
, " FILEFLAGSMASK 0x%x\n", (unsigned int) f
->file_flags_mask
);
3198 if (f
->file_flags
!= 0)
3199 fprintf (e
, " FILEFLAGS 0x%x\n", (unsigned int) f
->file_flags
);
3200 if (f
->file_os
!= 0)
3201 fprintf (e
, " FILEOS 0x%x\n", (unsigned int) f
->file_os
);
3202 if (f
->file_type
!= 0)
3203 fprintf (e
, " FILETYPE 0x%x\n", (unsigned int) f
->file_type
);
3204 if (f
->file_subtype
!= 0)
3205 fprintf (e
, " FILESUBTYPE 0x%x\n", (unsigned int) f
->file_subtype
);
3206 if (f
->file_date_ms
!= 0 || f
->file_date_ls
!= 0)
3207 fprintf (e
, "/* Date: %u, %u. */\n",
3208 (unsigned int) f
->file_date_ms
, (unsigned int) f
->file_date_ls
);
3210 fprintf (e
, "BEGIN\n");
3212 for (vi
= versioninfo
->var
; vi
!= NULL
; vi
= vi
->next
)
3216 case VERINFO_STRING
:
3218 const rc_ver_stringinfo
*vs
;
3220 fprintf (e
, " BLOCK \"StringFileInfo\"\n");
3221 fprintf (e
, " BEGIN\n");
3222 fprintf (e
, " BLOCK ");
3223 unicode_print_quoted (e
, vi
->u
.string
.language
, -1);
3225 fprintf (e
, " BEGIN\n");
3227 for (vs
= vi
->u
.string
.strings
; vs
!= NULL
; vs
= vs
->next
)
3229 fprintf (e
, " VALUE ");
3230 unicode_print_quoted (e
, vs
->key
, -1);
3232 unicode_print_quoted (e
, vs
->value
, -1);
3236 fprintf (e
, " END\n");
3237 fprintf (e
, " END\n");
3243 const rc_ver_varinfo
*vv
;
3245 fprintf (e
, " BLOCK \"VarFileInfo\"\n");
3246 fprintf (e
, " BEGIN\n");
3247 fprintf (e
, " VALUE ");
3248 unicode_print_quoted (e
, vi
->u
.var
.key
, -1);
3250 for (vv
= vi
->u
.var
.var
; vv
!= NULL
; vv
= vv
->next
)
3251 fprintf (e
, ", 0x%x, %d", (unsigned int) vv
->language
,
3254 fprintf (e
, "\n END\n");
3261 fprintf (e
, "END\n");
3265 rcdata_copy (const rc_rcdata_item
*src
, bfd_byte
*dst
)
3273 windres_put_16 (&wrtarget
, dst
, (rc_uint_type
) src
->u
.word
);
3277 windres_put_32 (&wrtarget
, dst
, (rc_uint_type
) src
->u
.dword
);
3280 if (dst
&& src
->u
.string
.length
)
3281 memcpy (dst
, src
->u
.string
.s
, src
->u
.string
.length
);
3282 return (rc_uint_type
) src
->u
.string
.length
;
3283 case RCDATA_WSTRING
:
3284 if (dst
&& src
->u
.wstring
.length
)
3285 memcpy (dst
, src
->u
.wstring
.w
, src
->u
.wstring
.length
* sizeof (unichar
));
3286 return (rc_uint_type
) (src
->u
.wstring
.length
* sizeof (unichar
));
3288 if (dst
&& src
->u
.buffer
.length
)
3289 memcpy (dst
, src
->u
.buffer
.data
, src
->u
.buffer
.length
);
3290 return (rc_uint_type
) src
->u
.buffer
.length
;
3294 /* Never reached. */