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 3 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 if (filename
== NULL
)
441 /* Setup the default resource import path taken from input file. */
442 else if (strchr (filename
, '/') != NULL
|| strchr (filename
, '\\') != NULL
)
446 if (filename
[0] == '/'
447 || filename
[0] == '\\'
448 || filename
[1] == ':')
450 edit
= dir
= xstrdup (filename
);
454 edit
= dir
= xmalloc (strlen (filename
) + 3);
455 sprintf (dir
, "./%s", filename
);
458 /* Walk dir backwards stopping at the first directory separator. */
459 edit
+= strlen (dir
);
460 while (edit
> dir
&& (edit
[-1] != '\\' && edit
[-1] != '/'))
466 /* Cut off trailing slash. */
470 /* Convert all back slashes to forward slashes. */
471 while ((edit
= strchr (dir
, '\\')) != NULL
)
474 windres_add_include_dir (dir
);
477 istream_type
= (use_temp_file
) ? ISTREAM_FILE
: ISTREAM_PIPE
;
479 if (preprocargs
== NULL
)
484 cmd
= xmalloc (strlen (preprocessor
)
485 + strlen (preprocargs
)
487 + strlen (fnquotes
) * 2
489 sprintf (cmd
, "%s %s %s%s%s", preprocessor
, preprocargs
,
490 fnquotes
, filename
, fnquotes
);
492 cpp_pipe
= open_input_stream (cmd
);
496 char *dash
, *slash
, *cp
;
498 preprocessor
= DEFAULT_PREPROCESSOR
;
500 cmd
= xmalloc (strlen (program_name
)
501 + strlen (preprocessor
)
502 + strlen (preprocargs
)
504 + strlen (fnquotes
) * 2
505 #ifdef HAVE_EXECUTABLE_SUFFIX
506 + strlen (EXECUTABLE_SUFFIX
)
512 for (cp
= program_name
; *cp
; cp
++)
517 #if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32)
518 *cp
== ':' || *cp
== '\\' ||
531 /* First, try looking for a prefixed gcc in the windres
532 directory, with the same prefix as windres */
534 cpp_pipe
= look_for_default (cmd
, program_name
, dash
- program_name
+ 1,
535 preprocargs
, filename
);
538 if (slash
&& ! cpp_pipe
)
540 /* Next, try looking for a gcc in the same directory as
543 cpp_pipe
= look_for_default (cmd
, program_name
, slash
- program_name
+ 1,
544 preprocargs
, filename
);
549 /* Sigh, try the default */
551 cpp_pipe
= look_for_default (cmd
, "", 0, preprocargs
, filename
);
558 rc_filename
= xstrdup (filename
);
561 rcparse_set_language (language
);
563 rcparse_discard_strings ();
565 close_input_stream ();
567 if (fontdirs
!= NULL
)
576 /* Close the input stream if it is open. */
579 close_input_stream (void)
581 if (istream_type
== ISTREAM_FILE
)
583 if (cpp_pipe
!= NULL
)
586 if (cpp_temp_file
!= NULL
)
588 int errno_save
= errno
;
590 unlink (cpp_temp_file
);
592 free (cpp_temp_file
);
597 if (cpp_pipe
!= NULL
)
600 err
= pclose (cpp_pipe
);
601 /* We are reading from a pipe, therefore we don't
602 know if cpp failed or succeeded until pclose. */
603 if (err
!= 0 || errno
== ECHILD
)
605 /* Since this is also run via xatexit, safeguard. */
607 cpp_temp_file
= NULL
;
608 fatal (_("preprocessing failed."));
613 /* Since this is also run via xatexit, safeguard. */
615 cpp_temp_file
= NULL
;
618 /* Report an error while reading an rc file. */
621 yyerror (const char *msg
)
623 fatal ("%s:%d: %s", rc_filename
, rc_lineno
, msg
);
626 /* Issue a warning while reading an rc file. */
629 rcparse_warning (const char *msg
)
631 fprintf (stderr
, _("%s:%d: %s\n"), rc_filename
, rc_lineno
, msg
);
634 /* Die if we get an unexpected end of file. */
637 unexpected_eof (const char *msg
)
639 fatal (_("%s: unexpected EOF"), msg
);
642 /* Read a 16 bit word from a file. The data is assumed to be little
646 get_word (FILE *e
, const char *msg
)
653 unexpected_eof (msg
);
654 return ((b2
& 0xff) << 8) | (b1
& 0xff);
657 /* Read a 32 bit word from a file. The data is assumed to be little
661 get_long (FILE *e
, const char *msg
)
670 unexpected_eof (msg
);
671 return (((((((b4
& 0xff) << 8)
677 /* Read data from a file. This is a wrapper to do error checking. */
680 get_data (FILE *e
, bfd_byte
*p
, rc_uint_type c
, const char *msg
)
682 rc_uint_type got
; // $$$d
684 got
= (rc_uint_type
) fread (p
, 1, c
, e
);
688 fatal (_("%s: read of %lu returned %lu"), msg
, (long) c
, (long) got
);
691 /* Define an accelerator resource. */
694 define_accelerator (rc_res_id id
, const rc_res_res_info
*resinfo
,
695 rc_accelerator
*data
)
699 r
= define_standard_resource (&resources
, RT_ACCELERATOR
, id
,
700 resinfo
->language
, 0);
701 r
->type
= RES_TYPE_ACCELERATOR
;
703 r
->res_info
= *resinfo
;
706 /* Define a bitmap resource. Bitmap data is stored in a file. The
707 first 14 bytes of the file are a standard header, which is not
708 included in the resource data. */
710 #define BITMAP_SKIP (14)
713 define_bitmap (rc_res_id id
, const rc_res_res_info
*resinfo
,
714 const char *filename
)
723 e
= open_file_search (filename
, FOPEN_RB
, "bitmap file", &real_filename
);
725 if (stat (real_filename
, &s
) < 0)
726 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
729 data
= (bfd_byte
*) res_alloc (s
.st_size
- BITMAP_SKIP
);
731 for (i
= 0; i
< BITMAP_SKIP
; i
++)
734 get_data (e
, data
, s
.st_size
- BITMAP_SKIP
, real_filename
);
737 free (real_filename
);
739 r
= define_standard_resource (&resources
, RT_BITMAP
, id
,
740 resinfo
->language
, 0);
742 r
->type
= RES_TYPE_BITMAP
;
743 r
->u
.data
.length
= s
.st_size
- BITMAP_SKIP
;
744 r
->u
.data
.data
= data
;
745 r
->res_info
= *resinfo
;
748 /* Define a cursor resource. A cursor file may contain a set of
749 bitmaps, each representing the same cursor at various different
750 resolutions. They each get written out with a different ID. The
751 real cursor resource is then a group resource which can be used to
752 select one of the actual cursors. */
755 define_cursor (rc_res_id id
, const rc_res_res_info
*resinfo
,
756 const char *filename
)
761 struct icondir
*icondirs
;
764 rc_group_cursor
*first
, **pp
;
766 e
= open_file_search (filename
, FOPEN_RB
, "cursor file", &real_filename
);
768 /* A cursor file is basically an icon file. The start of the file
769 is a three word structure. The first word is ignored. The
770 second word is the type of data. The third word is the number of
773 get_word (e
, real_filename
);
774 type
= get_word (e
, real_filename
);
775 count
= get_word (e
, real_filename
);
777 fatal (_("cursor file `%s' does not contain cursor data"), real_filename
);
779 /* Read in the icon directory entries. */
781 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
783 for (i
= 0; i
< count
; i
++)
785 icondirs
[i
].width
= getc (e
);
786 icondirs
[i
].height
= getc (e
);
787 icondirs
[i
].colorcount
= getc (e
);
789 icondirs
[i
].u
.cursor
.xhotspot
= get_word (e
, real_filename
);
790 icondirs
[i
].u
.cursor
.yhotspot
= get_word (e
, real_filename
);
791 icondirs
[i
].bytes
= get_long (e
, real_filename
);
792 icondirs
[i
].offset
= get_long (e
, real_filename
);
795 unexpected_eof (real_filename
);
798 /* Define each cursor as a unique resource. */
800 first_cursor
= cursors
;
802 for (i
= 0; i
< count
; i
++)
808 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
809 fatal (_("%s: fseek to %lu failed: %s"), real_filename
,
810 icondirs
[i
].offset
, strerror (errno
));
812 data
= (bfd_byte
*) res_alloc (icondirs
[i
].bytes
);
814 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
816 c
= (rc_cursor
*) res_alloc (sizeof (rc_cursor
));
817 c
->xhotspot
= icondirs
[i
].u
.cursor
.xhotspot
;
818 c
->yhotspot
= icondirs
[i
].u
.cursor
.yhotspot
;
819 c
->length
= icondirs
[i
].bytes
;
827 r
= define_standard_resource (&resources
, RT_CURSOR
, name
,
828 resinfo
->language
, 0);
829 r
->type
= RES_TYPE_CURSOR
;
831 r
->res_info
= *resinfo
;
835 free (real_filename
);
837 /* Define a cursor group resource. */
841 for (i
= 0; i
< count
; i
++)
845 cg
= (rc_group_cursor
*) res_alloc (sizeof (rc_group_cursor
));
847 cg
->width
= icondirs
[i
].width
;
848 cg
->height
= 2 * icondirs
[i
].height
;
850 /* FIXME: What should these be set to? */
854 cg
->bytes
= icondirs
[i
].bytes
+ 4;
855 cg
->index
= first_cursor
+ i
+ 1;
863 r
= define_standard_resource (&resources
, RT_GROUP_CURSOR
, id
,
864 resinfo
->language
, 0);
865 r
->type
= RES_TYPE_GROUP_CURSOR
;
866 r
->u
.group_cursor
= first
;
867 r
->res_info
= *resinfo
;
870 /* Define a dialog resource. */
873 define_dialog (rc_res_id id
, const rc_res_res_info
*resinfo
,
874 const rc_dialog
*dialog
)
879 copy
= (rc_dialog
*) res_alloc (sizeof *copy
);
882 r
= define_standard_resource (&resources
, RT_DIALOG
, id
,
883 resinfo
->language
, 0);
884 r
->type
= RES_TYPE_DIALOG
;
886 r
->res_info
= *resinfo
;
889 /* Define a dialog control. This does not define a resource, but
890 merely allocates and fills in a structure. */
893 define_control (const rc_res_id iid
, rc_uint_type id
, rc_uint_type x
,
894 rc_uint_type y
, rc_uint_type width
, rc_uint_type height
,
895 const rc_res_id
class, rc_uint_type style
,
896 rc_uint_type exstyle
)
898 rc_dialog_control
*n
;
900 n
= (rc_dialog_control
*) res_alloc (sizeof (rc_dialog_control
));
904 n
->exstyle
= exstyle
;
918 define_icon_control (rc_res_id iid
, rc_uint_type id
, rc_uint_type x
,
919 rc_uint_type y
, rc_uint_type style
,
920 rc_uint_type exstyle
, rc_uint_type help
,
921 rc_rcdata_item
*data
, rc_dialog_ex
*ex
)
923 rc_dialog_control
*n
;
928 style
= SS_ICON
| WS_CHILD
| WS_VISIBLE
;
929 res_string_to_id (&tid
, "");
931 cid
.u
.id
= CTL_STATIC
;
932 n
= define_control (tid
, id
, x
, y
, 0, 0, cid
, style
, exstyle
);
935 rcparse_warning (_("help ID requires DIALOGEX"));
937 rcparse_warning (_("control data requires DIALOGEX"));
944 /* Define a font resource. */
947 define_font (rc_res_id id
, const rc_res_res_info
*resinfo
,
948 const char *filename
)
959 const char *device
, *face
;
962 e
= open_file_search (filename
, FOPEN_RB
, "font file", &real_filename
);
964 if (stat (real_filename
, &s
) < 0)
965 fatal (_("stat failed on font file `%s': %s"), real_filename
,
968 data
= (bfd_byte
*) res_alloc (s
.st_size
);
970 get_data (e
, data
, s
.st_size
, real_filename
);
973 free (real_filename
);
975 r
= define_standard_resource (&resources
, RT_FONT
, id
,
976 resinfo
->language
, 0);
978 r
->type
= RES_TYPE_FONT
;
979 r
->u
.data
.length
= s
.st_size
;
980 r
->u
.data
.data
= data
;
981 r
->res_info
= *resinfo
;
983 /* For each font resource, we must add an entry in the FONTDIR
984 resource. The FONTDIR resource includes some strings in the font
985 file. To find them, we have to do some magic on the data we have
988 offset
= ((((((data
[47] << 8)
992 if (offset
> 0 && offset
< s
.st_size
)
993 device
= (char *) data
+ offset
;
997 offset
= ((((((data
[51] << 8)
1001 if (offset
> 0 && offset
< s
.st_size
)
1002 face
= (char *) data
+ offset
;
1008 fontdatalength
= 58 + strlen (device
) + strlen (face
);
1009 fontdata
= (bfd_byte
*) res_alloc (fontdatalength
);
1010 memcpy (fontdata
, data
, 56);
1011 strcpy ((char *) fontdata
+ 56, device
);
1012 strcpy ((char *) fontdata
+ 57 + strlen (device
), face
);
1014 fd
= (rc_fontdir
*) res_alloc (sizeof (rc_fontdir
));
1017 fd
->length
= fontdatalength
;
1018 fd
->data
= fontdata
;
1020 for (pp
= &fontdirs
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1024 /* For the single fontdirs resource, we always use the resource
1025 information of the last font. I don't know what else to do. */
1026 fontdirs_resinfo
= *resinfo
;
1030 define_font_rcdata (rc_res_id id
,const rc_res_res_info
*resinfo
,
1031 rc_rcdata_item
*data
)
1034 rc_uint_type len_data
;
1037 r
= define_standard_resource (&resources
, RT_FONT
, id
,
1038 resinfo
->language
, 0);
1040 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
1042 r
->type
= RES_TYPE_FONT
;
1043 r
->u
.data
.length
= len_data
;
1044 r
->u
.data
.data
= pb_data
;
1045 r
->res_info
= *resinfo
;
1048 /* Define the fontdirs resource. This is called after the entire rc
1049 file has been parsed, if any font resources were seen. */
1052 define_fontdirs (void)
1060 r
= define_standard_resource (&resources
, RT_FONTDIR
, id
, 0x409, 0);
1062 r
->type
= RES_TYPE_FONTDIR
;
1063 r
->u
.fontdir
= fontdirs
;
1064 r
->res_info
= fontdirs_resinfo
;
1068 rcdata_render_as_buffer (const rc_rcdata_item
*data
, rc_uint_type
*plen
)
1070 const rc_rcdata_item
*d
;
1071 bfd_byte
*ret
= NULL
, *pret
;
1072 rc_uint_type len
= 0;
1074 for (d
= data
; d
!= NULL
; d
= d
->next
)
1075 len
+= rcdata_copy (d
, NULL
);
1078 ret
= pret
= (bfd_byte
*) res_alloc (len
);
1079 for (d
= data
; d
!= NULL
; d
= d
->next
)
1080 pret
+= rcdata_copy (d
, pret
);
1088 define_fontdir_rcdata (rc_res_id id
,const rc_res_res_info
*resinfo
,
1089 rc_rcdata_item
*data
)
1092 rc_fontdir
*fd
, *fd_first
, *fd_cur
;
1093 rc_uint_type len_data
;
1097 fd_cur
= fd_first
= NULL
;
1098 r
= define_standard_resource (&resources
, RT_FONTDIR
, id
, 0x409, 0);
1100 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
1104 rc_uint_type off
= 2;
1105 c
= windres_get_16 (&wrtarget
, pb_data
, len_data
);
1109 rc_uint_type safe_pos
= off
;
1110 const struct bin_fontdir_item
*bfi
;
1112 bfi
= (const struct bin_fontdir_item
*) pb_data
+ off
;
1113 fd
= (rc_fontdir
*) res_alloc (sizeof (rc_fontdir
));
1114 fd
->index
= windres_get_16 (&wrtarget
, bfi
->index
, len_data
- off
);
1115 fd
->data
= pb_data
+ off
;
1117 len
= strlen ((char *) bfi
->device_name
) + 1;
1118 off
+= (rc_uint_type
) len
;
1119 off
+= (rc_uint_type
) strlen ((char *) bfi
->device_name
+ len
) + 1;
1120 fd
->length
= (off
- safe_pos
);
1122 if (fd_first
== NULL
)
1129 r
->type
= RES_TYPE_FONTDIR
;
1130 r
->u
.fontdir
= fd_first
;
1131 r
->res_info
= *resinfo
;
1134 static void define_messagetable_rcdata (rc_res_id id
, const rc_res_res_info
*resinfo
,
1135 rc_rcdata_item
*data
)
1138 rc_uint_type len_data
;
1141 r
= define_standard_resource (&resources
, RT_MESSAGETABLE
, id
, resinfo
->language
, 0);
1143 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
1144 r
->type
= RES_TYPE_MESSAGETABLE
;
1145 r
->u
.data
.length
= len_data
;
1146 r
->u
.data
.data
= pb_data
;
1147 r
->res_info
= *resinfo
;
1150 /* Define an icon resource. An icon file may contain a set of
1151 bitmaps, each representing the same icon at various different
1152 resolutions. They each get written out with a different ID. The
1153 real icon resource is then a group resource which can be used to
1154 select one of the actual icon bitmaps. */
1157 define_icon (rc_res_id id
, const rc_res_res_info
*resinfo
,
1158 const char *filename
)
1161 char *real_filename
;
1163 struct icondir
*icondirs
;
1166 rc_group_icon
*first
, **pp
;
1168 e
= open_file_search (filename
, FOPEN_RB
, "icon file", &real_filename
);
1170 /* The start of an icon file is a three word structure. The first
1171 word is ignored. The second word is the type of data. The third
1172 word is the number of entries. */
1174 get_word (e
, real_filename
);
1175 type
= get_word (e
, real_filename
);
1176 count
= get_word (e
, real_filename
);
1178 fatal (_("icon file `%s' does not contain icon data"), real_filename
);
1180 /* Read in the icon directory entries. */
1182 icondirs
= (struct icondir
*) xmalloc (count
* sizeof *icondirs
);
1184 for (i
= 0; i
< count
; i
++)
1186 icondirs
[i
].width
= getc (e
);
1187 icondirs
[i
].height
= getc (e
);
1188 icondirs
[i
].colorcount
= getc (e
);
1190 icondirs
[i
].u
.icon
.planes
= get_word (e
, real_filename
);
1191 icondirs
[i
].u
.icon
.bits
= get_word (e
, real_filename
);
1192 icondirs
[i
].bytes
= get_long (e
, real_filename
);
1193 icondirs
[i
].offset
= get_long (e
, real_filename
);
1196 unexpected_eof (real_filename
);
1199 /* Define each icon as a unique resource. */
1203 for (i
= 0; i
< count
; i
++)
1208 if (fseek (e
, icondirs
[i
].offset
, SEEK_SET
) != 0)
1209 fatal (_("%s: fseek to %lu failed: %s"), real_filename
,
1210 icondirs
[i
].offset
, strerror (errno
));
1212 data
= (bfd_byte
*) res_alloc (icondirs
[i
].bytes
);
1214 get_data (e
, data
, icondirs
[i
].bytes
, real_filename
);
1221 r
= define_standard_resource (&resources
, RT_ICON
, name
,
1222 resinfo
->language
, 0);
1223 r
->type
= RES_TYPE_ICON
;
1224 r
->u
.data
.length
= icondirs
[i
].bytes
;
1225 r
->u
.data
.data
= data
;
1226 r
->res_info
= *resinfo
;
1230 free (real_filename
);
1232 /* Define an icon group resource. */
1236 for (i
= 0; i
< count
; i
++)
1240 /* For some reason, at least in some files the planes and bits
1241 are zero. We instead set them from the color. This is
1244 cg
= (rc_group_icon
*) res_alloc (sizeof (rc_group_icon
));
1246 cg
->width
= icondirs
[i
].width
;
1247 cg
->height
= icondirs
[i
].height
;
1248 cg
->colors
= icondirs
[i
].colorcount
;
1250 if (icondirs
[i
].u
.icon
.planes
)
1251 cg
->planes
= icondirs
[i
].u
.icon
.planes
;
1255 if (icondirs
[i
].u
.icon
.bits
)
1256 cg
->bits
= icondirs
[i
].u
.icon
.bits
;
1261 while ((1L << cg
->bits
) < cg
->colors
)
1265 cg
->bytes
= icondirs
[i
].bytes
;
1266 cg
->index
= first_icon
+ i
+ 1;
1274 r
= define_standard_resource (&resources
, RT_GROUP_ICON
, id
,
1275 resinfo
->language
, 0);
1276 r
->type
= RES_TYPE_GROUP_ICON
;
1277 r
->u
.group_icon
= first
;
1278 r
->res_info
= *resinfo
;
1282 define_group_icon_rcdata (rc_res_id id
, const rc_res_res_info
*resinfo
,
1283 rc_rcdata_item
*data
)
1286 rc_group_icon
*cg
, *first
, *cur
;
1287 rc_uint_type len_data
;
1290 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
1295 while (len_data
>= 6)
1298 unsigned short type
;
1299 type
= windres_get_16 (&wrtarget
, pb_data
+ 2, len_data
- 2);
1301 fatal (_("unexpected group icon type %d"), type
);
1302 c
= windres_get_16 (&wrtarget
, pb_data
+ 4, len_data
- 4);
1306 for (i
= 0; i
< c
; i
++)
1309 fatal ("too small group icon rcdata");
1310 cg
= (rc_group_icon
*) res_alloc (sizeof (rc_group_icon
));
1312 cg
->width
= pb_data
[0];
1313 cg
->height
= pb_data
[1];
1314 cg
->colors
= pb_data
[2];
1315 cg
->planes
= windres_get_16 (&wrtarget
, pb_data
+ 4, len_data
- 4);
1316 cg
->bits
= windres_get_16 (&wrtarget
, pb_data
+ 6, len_data
- 6);
1317 cg
->bytes
= windres_get_32 (&wrtarget
, pb_data
+ 8, len_data
- 8);
1318 cg
->index
= windres_get_16 (&wrtarget
, pb_data
+ 12, len_data
- 12);
1328 r
= define_standard_resource (&resources
, RT_GROUP_ICON
, id
,
1329 resinfo
->language
, 0);
1330 r
->type
= RES_TYPE_GROUP_ICON
;
1331 r
->u
.group_icon
= first
;
1332 r
->res_info
= *resinfo
;
1336 define_group_cursor_rcdata (rc_res_id id
, const rc_res_res_info
*resinfo
,
1337 rc_rcdata_item
*data
)
1340 rc_group_cursor
*cg
, *first
, *cur
;
1341 rc_uint_type len_data
;
1344 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
1348 while (len_data
>= 6)
1351 unsigned short type
;
1352 type
= windres_get_16 (&wrtarget
, pb_data
+ 2, len_data
- 2);
1354 fatal (_("unexpected group cursor type %d"), type
);
1355 c
= windres_get_16 (&wrtarget
, pb_data
+ 4, len_data
- 4);
1359 for (i
= 0; i
< c
; i
++)
1362 fatal ("too small group icon rcdata");
1363 cg
= (rc_group_cursor
*) res_alloc (sizeof (rc_group_cursor
));
1365 cg
->width
= windres_get_16 (&wrtarget
, pb_data
, len_data
);
1366 cg
->height
= windres_get_16 (&wrtarget
, pb_data
+ 2, len_data
- 2);
1367 cg
->planes
= windres_get_16 (&wrtarget
, pb_data
+ 4, len_data
- 4);
1368 cg
->bits
= windres_get_16 (&wrtarget
, pb_data
+ 6, len_data
- 6);
1369 cg
->bytes
= windres_get_32 (&wrtarget
, pb_data
+ 8, len_data
- 8);
1370 cg
->index
= windres_get_16 (&wrtarget
, pb_data
+ 12, len_data
- 12);
1381 r
= define_standard_resource (&resources
, RT_GROUP_ICON
, id
,
1382 resinfo
->language
, 0);
1383 r
->type
= RES_TYPE_GROUP_CURSOR
;
1384 r
->u
.group_cursor
= first
;
1385 r
->res_info
= *resinfo
;
1389 define_cursor_rcdata (rc_res_id id
, const rc_res_res_info
*resinfo
,
1390 rc_rcdata_item
*data
)
1394 rc_uint_type len_data
;
1397 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
1399 c
= (rc_cursor
*) res_alloc (sizeof (rc_cursor
));
1400 c
->xhotspot
= windres_get_16 (&wrtarget
, pb_data
, len_data
);
1401 c
->yhotspot
= windres_get_16 (&wrtarget
, pb_data
+ 2, len_data
- 2);
1402 c
->length
= len_data
- BIN_CURSOR_SIZE
;
1403 c
->data
= (const bfd_byte
*) (data
+ BIN_CURSOR_SIZE
);
1405 r
= define_standard_resource (&resources
, RT_CURSOR
, id
, resinfo
->language
, 0);
1406 r
->type
= RES_TYPE_CURSOR
;
1408 r
->res_info
= *resinfo
;
1412 define_bitmap_rcdata (rc_res_id id
, const rc_res_res_info
*resinfo
,
1413 rc_rcdata_item
*data
)
1416 rc_uint_type len_data
;
1419 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
1421 r
= define_standard_resource (&resources
, RT_BITMAP
, id
, resinfo
->language
, 0);
1422 r
->type
= RES_TYPE_BITMAP
;
1423 r
->u
.data
.length
= len_data
;
1424 r
->u
.data
.data
= pb_data
;
1425 r
->res_info
= *resinfo
;
1429 define_icon_rcdata (rc_res_id id
, const rc_res_res_info
*resinfo
,
1430 rc_rcdata_item
*data
)
1433 rc_uint_type len_data
;
1436 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
1438 r
= define_standard_resource (&resources
, RT_ICON
, id
, resinfo
->language
, 0);
1439 r
->type
= RES_TYPE_ICON
;
1440 r
->u
.data
.length
= len_data
;
1441 r
->u
.data
.data
= pb_data
;
1442 r
->res_info
= *resinfo
;
1445 /* Define a menu resource. */
1448 define_menu (rc_res_id id
, const rc_res_res_info
*resinfo
,
1449 rc_menuitem
*menuitems
)
1454 m
= (rc_menu
*) res_alloc (sizeof (rc_menu
));
1455 m
->items
= menuitems
;
1458 r
= define_standard_resource (&resources
, RT_MENU
, id
, resinfo
->language
, 0);
1459 r
->type
= RES_TYPE_MENU
;
1461 r
->res_info
= *resinfo
;
1464 /* Define a menu item. This does not define a resource, but merely
1465 allocates and fills in a structure. */
1468 define_menuitem (const unichar
*text
, rc_uint_type menuid
, rc_uint_type type
,
1469 rc_uint_type state
, rc_uint_type help
,
1470 rc_menuitem
*menuitems
)
1474 mi
= (rc_menuitem
*) res_alloc (sizeof (rc_menuitem
));
1479 mi
->text
= unichar_dup (text
);
1481 mi
->popup
= menuitems
;
1485 /* Define a messagetable resource. */
1488 define_messagetable (rc_res_id id
, const rc_res_res_info
*resinfo
,
1489 const char *filename
)
1492 char *real_filename
;
1497 e
= open_file_search (filename
, FOPEN_RB
, "messagetable file",
1500 if (stat (real_filename
, &s
) < 0)
1501 fatal (_("stat failed on bitmap file `%s': %s"), real_filename
,
1504 data
= (bfd_byte
*) res_alloc (s
.st_size
);
1506 get_data (e
, data
, s
.st_size
, real_filename
);
1509 free (real_filename
);
1511 r
= define_standard_resource (&resources
, RT_MESSAGETABLE
, id
,
1512 resinfo
->language
, 0);
1514 r
->type
= RES_TYPE_MESSAGETABLE
;
1515 r
->u
.data
.length
= s
.st_size
;
1516 r
->u
.data
.data
= data
;
1517 r
->res_info
= *resinfo
;
1520 /* Define an rcdata resource. */
1523 define_rcdata (rc_res_id id
, const rc_res_res_info
*resinfo
,
1524 rc_rcdata_item
*data
)
1528 r
= define_standard_resource (&resources
, RT_RCDATA
, id
,
1529 resinfo
->language
, 0);
1530 r
->type
= RES_TYPE_RCDATA
;
1532 r
->res_info
= *resinfo
;
1535 /* Create an rcdata item holding a string. */
1538 define_rcdata_string (const char *string
, rc_uint_type len
)
1543 ri
= (rc_rcdata_item
*) res_alloc (sizeof (rc_rcdata_item
));
1545 ri
->type
= RCDATA_STRING
;
1546 ri
->u
.string
.length
= len
;
1547 s
= (char *) res_alloc (len
);
1548 memcpy (s
, string
, len
);
1554 /* Create an rcdata item holding a unicode string. */
1557 define_rcdata_unistring (const unichar
*string
, rc_uint_type len
)
1562 ri
= (rc_rcdata_item
*) res_alloc (sizeof (rc_rcdata_item
));
1564 ri
->type
= RCDATA_WSTRING
;
1565 ri
->u
.wstring
.length
= len
;
1566 s
= (unichar
*) res_alloc (len
* sizeof (unichar
));
1567 memcpy (s
, string
, len
* sizeof (unichar
));
1568 ri
->u
.wstring
.w
= s
;
1573 /* Create an rcdata item holding a number. */
1576 define_rcdata_number (rc_uint_type val
, int dword
)
1580 ri
= (rc_rcdata_item
*) res_alloc (sizeof (rc_rcdata_item
));
1582 ri
->type
= dword
? RCDATA_DWORD
: RCDATA_WORD
;
1588 /* Define a stringtable resource. This is called for each string
1589 which appears in a STRINGTABLE statement. */
1592 define_stringtable (const rc_res_res_info
*resinfo
,
1593 rc_uint_type stringid
, const unichar
*string
)
1599 id
.u
.id
= (stringid
>> 4) + 1;
1600 r
= define_standard_resource (&resources
, RT_STRING
, id
,
1601 resinfo
->language
, 1);
1603 if (r
->type
== RES_TYPE_UNINITIALIZED
)
1607 r
->type
= RES_TYPE_STRINGTABLE
;
1608 r
->u
.stringtable
= ((rc_stringtable
*)
1609 res_alloc (sizeof (rc_stringtable
)));
1610 for (i
= 0; i
< 16; i
++)
1612 r
->u
.stringtable
->strings
[i
].length
= 0;
1613 r
->u
.stringtable
->strings
[i
].string
= NULL
;
1616 r
->res_info
= *resinfo
;
1619 r
->u
.stringtable
->strings
[stringid
& 0xf].length
= unichar_len (string
);
1620 r
->u
.stringtable
->strings
[stringid
& 0xf].string
= unichar_dup (string
);
1624 define_toolbar (rc_res_id id
, rc_res_res_info
*resinfo
, rc_uint_type width
, rc_uint_type height
,
1625 rc_toolbar_item
*items
)
1630 t
= (rc_toolbar
*) res_alloc (sizeof (rc_toolbar
));
1631 t
->button_width
= width
;
1632 t
->button_height
= height
;
1635 while (items
!= NULL
)
1638 items
= items
->next
;
1640 r
= define_standard_resource (&resources
, RT_TOOLBAR
, id
, resinfo
->language
, 0);
1641 r
->type
= RES_TYPE_TOOLBAR
;
1643 r
->res_info
= *resinfo
;
1646 /* Define a user data resource where the data is in the rc file. */
1649 define_user_data (rc_res_id id
, rc_res_id type
,
1650 const rc_res_res_info
*resinfo
,
1651 rc_rcdata_item
*data
)
1656 rc_uint_type len_data
;
1658 /* We have to check if the binary data is parsed specially. */
1659 if (type
.named
== 0)
1664 define_fontdir_rcdata (id
, resinfo
, data
);
1667 define_font_rcdata (id
, resinfo
, data
);
1670 define_icon_rcdata (id
, resinfo
, data
);
1673 define_bitmap_rcdata (id
, resinfo
, data
);
1676 define_cursor_rcdata (id
, resinfo
, data
);
1679 define_group_icon_rcdata (id
, resinfo
, data
);
1681 case RT_GROUP_CURSOR
:
1682 define_group_cursor_rcdata (id
, resinfo
, data
);
1684 case RT_MESSAGETABLE
:
1685 define_messagetable_rcdata (id
, resinfo
, data
);
1688 /* Treat as normal user-data. */
1695 ids
[2].u
.id
= resinfo
->language
;
1697 r
= define_resource (& resources
, 3, ids
, 0);
1698 r
->type
= RES_TYPE_USERDATA
;
1699 r
->u
.userdata
= ((rc_rcdata_item
*)
1700 res_alloc (sizeof (rc_rcdata_item
)));
1701 r
->u
.userdata
->next
= NULL
;
1702 r
->u
.userdata
->type
= RCDATA_BUFFER
;
1703 pb_data
= rcdata_render_as_buffer (data
, &len_data
);
1704 r
->u
.userdata
->u
.buffer
.length
= len_data
;
1705 r
->u
.userdata
->u
.buffer
.data
= pb_data
;
1706 r
->res_info
= *resinfo
;
1710 define_rcdata_file (rc_res_id id
, const rc_res_res_info
*resinfo
,
1711 const char *filename
)
1715 char *real_filename
;
1719 e
= open_file_search (filename
, FOPEN_RB
, "file", &real_filename
);
1722 if (stat (real_filename
, &s
) < 0)
1723 fatal (_("stat failed on file `%s': %s"), real_filename
,
1726 data
= (bfd_byte
*) res_alloc (s
.st_size
);
1728 get_data (e
, data
, s
.st_size
, real_filename
);
1731 free (real_filename
);
1733 ri
= (rc_rcdata_item
*) res_alloc (sizeof (rc_rcdata_item
));
1735 ri
->type
= RCDATA_BUFFER
;
1736 ri
->u
.buffer
.length
= s
.st_size
;
1737 ri
->u
.buffer
.data
= data
;
1739 define_rcdata (id
, resinfo
, ri
);
1742 /* Define a user data resource where the data is in a file. */
1745 define_user_file (rc_res_id id
, rc_res_id type
,
1746 const rc_res_res_info
*resinfo
, const char *filename
)
1749 char *real_filename
;
1755 e
= open_file_search (filename
, FOPEN_RB
, "file", &real_filename
);
1757 if (stat (real_filename
, &s
) < 0)
1758 fatal (_("stat failed on file `%s': %s"), real_filename
,
1761 data
= (bfd_byte
*) res_alloc (s
.st_size
);
1763 get_data (e
, data
, s
.st_size
, real_filename
);
1766 free (real_filename
);
1771 ids
[2].u
.id
= resinfo
->language
;
1773 r
= define_resource (&resources
, 3, ids
, 0);
1774 r
->type
= RES_TYPE_USERDATA
;
1775 r
->u
.userdata
= ((rc_rcdata_item
*)
1776 res_alloc (sizeof (rc_rcdata_item
)));
1777 r
->u
.userdata
->next
= NULL
;
1778 r
->u
.userdata
->type
= RCDATA_BUFFER
;
1779 r
->u
.userdata
->u
.buffer
.length
= s
.st_size
;
1780 r
->u
.userdata
->u
.buffer
.data
= data
;
1781 r
->res_info
= *resinfo
;
1784 /* Define a versioninfo resource. */
1787 define_versioninfo (rc_res_id id
, rc_uint_type language
,
1788 rc_fixed_versioninfo
*fixedverinfo
,
1789 rc_ver_info
*verinfo
)
1793 r
= define_standard_resource (&resources
, RT_VERSION
, id
, language
, 0);
1794 r
->type
= RES_TYPE_VERSIONINFO
;
1795 r
->u
.versioninfo
= ((rc_versioninfo
*)
1796 res_alloc (sizeof (rc_versioninfo
)));
1797 r
->u
.versioninfo
->fixed
= fixedverinfo
;
1798 r
->u
.versioninfo
->var
= verinfo
;
1799 r
->res_info
.language
= language
;
1802 /* Add string version info to a list of version information. */
1805 append_ver_stringfileinfo (rc_ver_info
*verinfo
, const char *language
,
1806 rc_ver_stringinfo
*strings
)
1808 rc_ver_info
*vi
, **pp
;
1810 vi
= (rc_ver_info
*) res_alloc (sizeof (rc_ver_info
));
1812 vi
->type
= VERINFO_STRING
;
1813 unicode_from_ascii ((rc_uint_type
*) NULL
, &vi
->u
.string
.language
, language
);
1814 vi
->u
.string
.strings
= strings
;
1816 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1823 /* Add variable version info to a list of version information. */
1826 append_ver_varfileinfo (rc_ver_info
*verinfo
, const unichar
*key
,
1827 rc_ver_varinfo
*var
)
1829 rc_ver_info
*vi
, **pp
;
1831 vi
= (rc_ver_info
*) res_alloc (sizeof *vi
);
1833 vi
->type
= VERINFO_VAR
;
1834 vi
->u
.var
.key
= unichar_dup (key
);
1835 vi
->u
.var
.var
= var
;
1837 for (pp
= &verinfo
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1844 /* Append version string information to a list. */
1847 append_verval (rc_ver_stringinfo
*strings
, const unichar
*key
,
1848 const unichar
*value
)
1850 rc_ver_stringinfo
*vs
, **pp
;
1852 vs
= (rc_ver_stringinfo
*) res_alloc (sizeof (rc_ver_stringinfo
));
1854 vs
->key
= unichar_dup (key
);
1855 vs
->value
= unichar_dup (value
);
1857 for (pp
= &strings
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1864 /* Append version variable information to a list. */
1867 append_vertrans (rc_ver_varinfo
*var
, rc_uint_type language
,
1868 rc_uint_type charset
)
1870 rc_ver_varinfo
*vv
, **pp
;
1872 vv
= (rc_ver_varinfo
*) res_alloc (sizeof (rc_ver_varinfo
));
1874 vv
->language
= language
;
1875 vv
->charset
= charset
;
1877 for (pp
= &var
; *pp
!= NULL
; pp
= &(*pp
)->next
)
1884 /* Local functions used to write out an rc file. */
1886 static void indent (FILE *, int);
1887 static void write_rc_directory (FILE *, const rc_res_directory
*, const rc_res_id
*,
1888 const rc_res_id
*, rc_uint_type
*, int);
1889 static void write_rc_subdir (FILE *, const rc_res_entry
*, const rc_res_id
*,
1890 const rc_res_id
*, rc_uint_type
*, int);
1891 static void write_rc_resource (FILE *, const rc_res_id
*, const rc_res_id
*,
1892 const rc_res_resource
*, rc_uint_type
*);
1893 static void write_rc_accelerators (FILE *, const rc_accelerator
*);
1894 static void write_rc_cursor (FILE *, const rc_cursor
*);
1895 static void write_rc_group_cursor (FILE *, const rc_group_cursor
*);
1896 static void write_rc_dialog (FILE *, const rc_dialog
*);
1897 static void write_rc_dialog_control (FILE *, const rc_dialog_control
*);
1898 static void write_rc_fontdir (FILE *, const rc_fontdir
*);
1899 static void write_rc_group_icon (FILE *, const rc_group_icon
*);
1900 static void write_rc_menu (FILE *, const rc_menu
*, int);
1901 static void write_rc_toolbar (FILE *, const rc_toolbar
*);
1902 static void write_rc_menuitems (FILE *, const rc_menuitem
*, int, int);
1903 static void write_rc_messagetable (FILE *, rc_uint_type
, const bfd_byte
*);
1905 static void write_rc_datablock (FILE *, rc_uint_type
, const bfd_byte
*, int, int, int);
1906 static void write_rc_rcdata (FILE *, const rc_rcdata_item
*, int);
1907 static void write_rc_stringtable (FILE *, const rc_res_id
*, const rc_stringtable
*);
1908 static void write_rc_versioninfo (FILE *, const rc_versioninfo
*);
1910 /* Indent a given number of spaces. */
1913 indent (FILE *e
, int c
)
1917 for (i
= 0; i
< c
; i
++)
1921 /* Dump the resources we have read in the format of an rc file.
1923 Reasoned by the fact, that some resources need to be stored into file and
1924 refer to that file, we use the user-data model for that to express it binary
1925 without the need to store it somewhere externally. */
1928 write_rc_file (const char *filename
, const rc_res_directory
*resources
)
1931 rc_uint_type language
;
1933 if (filename
== NULL
)
1937 e
= fopen (filename
, FOPEN_WT
);
1939 fatal (_("can't open `%s' for output: %s"), filename
, strerror (errno
));
1942 language
= (rc_uint_type
) ((bfd_signed_vma
) -1);
1943 write_rc_directory (e
, resources
, (const rc_res_id
*) NULL
,
1944 (const rc_res_id
*) NULL
, &language
, 1);
1947 /* Write out a directory. E is the file to write to. RD is the
1948 directory. TYPE is a pointer to the level 1 ID which serves as the
1949 resource type. NAME is a pointer to the level 2 ID which serves as
1950 an individual resource name. LANGUAGE is a pointer to the current
1951 language. LEVEL is the level in the tree. */
1954 write_rc_directory (FILE *e
, const rc_res_directory
*rd
,
1955 const rc_res_id
*type
, const rc_res_id
*name
,
1956 rc_uint_type
*language
, int level
)
1958 const rc_res_entry
*re
;
1960 /* Print out some COFF information that rc files can't represent. */
1961 if (rd
->time
!= 0 || rd
->characteristics
!= 0 || rd
->major
!= 0 || rd
->minor
!= 0)
1963 wr_printcomment (e
, "COFF information not part of RC");
1965 wr_printcomment (e
, "Time stamp: %u", rd
->time
);
1966 if (rd
->characteristics
!= 0)
1967 wr_printcomment (e
, "Characteristics: %u", rd
->characteristics
);
1968 if (rd
->major
!= 0 || rd
->minor
!= 0)
1969 wr_printcomment (e
, "Version major:%d minor:%d", rd
->major
, rd
->minor
);
1972 for (re
= rd
->entries
; re
!= NULL
; re
= re
->next
)
1977 /* If we're at level 1, the key of this resource is the
1978 type. This normally duplicates the information we have
1979 stored with the resource itself, but we need to remember
1980 the type if this is a user define resource type. */
1985 /* If we're at level 2, the key of this resource is the name
1986 we are going to use in the rc printout. */
1991 /* If we're at level 3, then this key represents a language.
1992 Use it to update the current language. */
1994 && re
->id
.u
.id
!= (unsigned long) (unsigned int) *language
1995 && (re
->id
.u
.id
& 0xffff) == re
->id
.u
.id
)
1997 wr_print (e
, "LANGUAGE %u, %u\n",
1998 re
->id
.u
.id
& ((1 << SUBLANG_SHIFT
) - 1),
1999 (re
->id
.u
.id
>> SUBLANG_SHIFT
) & 0xff);
2000 *language
= re
->id
.u
.id
;
2009 write_rc_subdir (e
, re
, type
, name
, language
, level
);
2014 /* This is the normal case: the three levels are
2015 TYPE/NAME/LANGUAGE. NAME will have been set at level
2016 2, and represents the name to use. We probably just
2017 set LANGUAGE, and it will probably match what the
2018 resource itself records if anything. */
2019 write_rc_resource (e
, type
, name
, re
->u
.res
, language
);
2023 wr_printcomment (e
, "Resource at unexpected level %d", level
);
2024 write_rc_resource (e
, type
, (rc_res_id
*) NULL
, re
->u
.res
,
2029 if (rd
->entries
== NULL
)
2035 /* Write out a subdirectory entry. E is the file to write to. RE is
2036 the subdirectory entry. TYPE and NAME are pointers to higher level
2037 IDs, or NULL. LANGUAGE is a pointer to the current language.
2038 LEVEL is the level in the tree. */
2041 write_rc_subdir (FILE *e
, const rc_res_entry
*re
,
2042 const rc_res_id
*type
, const rc_res_id
*name
,
2043 rc_uint_type
*language
, int level
)
2049 wr_printcomment (e
, "Type: ");
2051 res_id_print (e
, re
->id
, 1);
2056 switch (re
->id
.u
.id
)
2058 case RT_CURSOR
: s
= "cursor"; break;
2059 case RT_BITMAP
: s
= "bitmap"; break;
2060 case RT_ICON
: s
= "icon"; break;
2061 case RT_MENU
: s
= "menu"; break;
2062 case RT_DIALOG
: s
= "dialog"; break;
2063 case RT_STRING
: s
= "stringtable"; break;
2064 case RT_FONTDIR
: s
= "fontdir"; break;
2065 case RT_FONT
: s
= "font"; break;
2066 case RT_ACCELERATOR
: s
= "accelerators"; break;
2067 case RT_RCDATA
: s
= "rcdata"; break;
2068 case RT_MESSAGETABLE
: s
= "messagetable"; break;
2069 case RT_GROUP_CURSOR
: s
= "group cursor"; break;
2070 case RT_GROUP_ICON
: s
= "group icon"; break;
2071 case RT_VERSION
: s
= "version"; break;
2072 case RT_DLGINCLUDE
: s
= "dlginclude"; break;
2073 case RT_PLUGPLAY
: s
= "plugplay"; break;
2074 case RT_VXD
: s
= "vxd"; break;
2075 case RT_ANICURSOR
: s
= "anicursor"; break;
2076 case RT_ANIICON
: s
= "aniicon"; break;
2077 case RT_TOOLBAR
: s
= "toolbar"; break;
2078 case RT_HTML
: s
= "html"; break;
2079 default: s
= NULL
; break;
2083 fprintf (e
, "%s", s
);
2085 res_id_print (e
, re
->id
, 1);
2090 wr_printcomment (e
, "Name: ");
2091 res_id_print (e
, re
->id
, 1);
2095 wr_printcomment (e
, "Language: ");
2096 res_id_print (e
, re
->id
, 1);
2100 wr_printcomment (e
, "Level %d: ", level
);
2101 res_id_print (e
, re
->id
, 1);
2104 write_rc_directory (e
, re
->u
.dir
, type
, name
, language
, level
+ 1);
2107 /* Write out a single resource. E is the file to write to. TYPE is a
2108 pointer to the type of the resource. NAME is a pointer to the name
2109 of the resource; it will be NULL if there is a level mismatch. RES
2110 is the resource data. LANGUAGE is a pointer to the current
2114 write_rc_resource (FILE *e
, const rc_res_id
*type
,
2115 const rc_res_id
*name
, const rc_res_resource
*res
,
2116 rc_uint_type
*language
)
2127 case RES_TYPE_ACCELERATOR
:
2129 rt
= RT_ACCELERATOR
;
2132 case RES_TYPE_BITMAP
:
2133 s
= "2 /* RT_BITMAP */";
2137 case RES_TYPE_CURSOR
:
2138 s
= "1 /* RT_CURSOR */";
2142 case RES_TYPE_GROUP_CURSOR
:
2143 s
= "12 /* RT_GROUP_CURSOR */";
2144 rt
= RT_GROUP_CURSOR
;
2147 case RES_TYPE_DIALOG
:
2148 if (extended_dialog (res
->u
.dialog
))
2156 s
= "8 /* RT_FONT */";
2160 case RES_TYPE_FONTDIR
:
2161 s
= "7 /* RT_FONTDIR */";
2166 s
= "3 /* RT_ICON */";
2170 case RES_TYPE_GROUP_ICON
:
2171 s
= "14 /* RT_GROUP_ICON */";
2176 if (extended_menu (res
->u
.menu
))
2189 case RES_TYPE_MESSAGETABLE
:
2190 s
= "11 /* RT_MESSAGETABLE */";
2191 rt
= RT_MESSAGETABLE
;
2194 case RES_TYPE_RCDATA
:
2199 case RES_TYPE_STRINGTABLE
:
2204 case RES_TYPE_USERDATA
:
2209 case RES_TYPE_VERSIONINFO
:
2214 case RES_TYPE_TOOLBAR
:
2222 && (type
->named
|| type
->u
.id
!= (unsigned long) rt
))
2224 wr_printcomment (e
, "Unexpected resource type mismatch: ");
2225 res_id_print (e
, *type
, 1);
2226 fprintf (e
, " != %d", rt
);
2229 if (res
->coff_info
.codepage
!= 0)
2230 wr_printcomment (e
, "Code page: %u", res
->coff_info
.codepage
);
2231 if (res
->coff_info
.reserved
!= 0)
2232 wr_printcomment (e
, "COFF reserved value: %u", res
->coff_info
.reserved
);
2235 if (rt
== RT_STRING
)
2240 res_id_print (e
, *name
, 1);
2242 fprintf (e
, "??Unknown-Name??");
2247 fprintf (e
, "%s", s
);
2248 else if (type
!= NULL
)
2250 if (type
->named
== 0)
2252 #define PRINT_RT_NAME(NAME) case NAME: \
2253 fprintf (e, "%u /* %s */", (unsigned int) NAME, #NAME); \
2259 res_id_print (e
, *type
, 0);
2262 PRINT_RT_NAME(RT_MANIFEST
);
2263 PRINT_RT_NAME(RT_ANICURSOR
);
2264 PRINT_RT_NAME(RT_ANIICON
);
2265 PRINT_RT_NAME(RT_RCDATA
);
2266 PRINT_RT_NAME(RT_ICON
);
2267 PRINT_RT_NAME(RT_CURSOR
);
2268 PRINT_RT_NAME(RT_BITMAP
);
2269 PRINT_RT_NAME(RT_PLUGPLAY
);
2270 PRINT_RT_NAME(RT_VXD
);
2271 PRINT_RT_NAME(RT_FONT
);
2272 PRINT_RT_NAME(RT_FONTDIR
);
2273 PRINT_RT_NAME(RT_HTML
);
2274 PRINT_RT_NAME(RT_MESSAGETABLE
);
2275 PRINT_RT_NAME(RT_DLGINCLUDE
);
2276 PRINT_RT_NAME(RT_DLGINIT
);
2278 #undef PRINT_RT_NAME
2281 res_id_print (e
, *type
, 1);
2284 fprintf (e
, "??Unknown-Type??");
2286 if (res
->res_info
.memflags
!= 0)
2288 if ((res
->res_info
.memflags
& MEMFLAG_MOVEABLE
) != 0)
2289 fprintf (e
, " MOVEABLE");
2290 if ((res
->res_info
.memflags
& MEMFLAG_PURE
) != 0)
2291 fprintf (e
, " PURE");
2292 if ((res
->res_info
.memflags
& MEMFLAG_PRELOAD
) != 0)
2293 fprintf (e
, " PRELOAD");
2294 if ((res
->res_info
.memflags
& MEMFLAG_DISCARDABLE
) != 0)
2295 fprintf (e
, " DISCARDABLE");
2298 if (res
->type
== RES_TYPE_DIALOG
)
2300 fprintf (e
, " %d, %d, %d, %d",
2301 (int) res
->u
.dialog
->x
, (int) res
->u
.dialog
->y
,
2302 (int) res
->u
.dialog
->width
, (int) res
->u
.dialog
->height
);
2303 if (res
->u
.dialog
->ex
!= NULL
2304 && res
->u
.dialog
->ex
->help
!= 0)
2305 fprintf (e
, ", %u", (unsigned int) res
->u
.dialog
->ex
->help
);
2307 else if (res
->type
== RES_TYPE_TOOLBAR
)
2309 fprintf (e
, " %d, %d", (int) res
->u
.toolbar
->button_width
,
2310 (int) res
->u
.toolbar
->button_height
);
2315 if ((res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
2316 || res
->res_info
.characteristics
!= 0
2317 || res
->res_info
.version
!= 0)
2323 case RES_TYPE_ACCELERATOR
:
2324 case RES_TYPE_DIALOG
:
2326 case RES_TYPE_RCDATA
:
2327 case RES_TYPE_STRINGTABLE
:
2336 if (res
->res_info
.language
!= 0 && res
->res_info
.language
!= *language
)
2337 fprintf (e
, "%sLANGUAGE %d, %d\n",
2338 modifiers
? "// " : "",
2339 (int) res
->res_info
.language
& ((1<<SUBLANG_SHIFT
)-1),
2340 (int) (res
->res_info
.language
>> SUBLANG_SHIFT
) & 0xff);
2341 if (res
->res_info
.characteristics
!= 0)
2342 fprintf (e
, "%sCHARACTERISTICS %u\n",
2343 modifiers
? "// " : "",
2344 (unsigned int) res
->res_info
.characteristics
);
2345 if (res
->res_info
.version
!= 0)
2346 fprintf (e
, "%sVERSION %u\n",
2347 modifiers
? "// " : "",
2348 (unsigned int) res
->res_info
.version
);
2356 case RES_TYPE_ACCELERATOR
:
2357 write_rc_accelerators (e
, res
->u
.acc
);
2360 case RES_TYPE_CURSOR
:
2361 write_rc_cursor (e
, res
->u
.cursor
);
2364 case RES_TYPE_GROUP_CURSOR
:
2365 write_rc_group_cursor (e
, res
->u
.group_cursor
);
2368 case RES_TYPE_DIALOG
:
2369 write_rc_dialog (e
, res
->u
.dialog
);
2372 case RES_TYPE_FONTDIR
:
2373 write_rc_fontdir (e
, res
->u
.fontdir
);
2376 case RES_TYPE_GROUP_ICON
:
2377 write_rc_group_icon (e
, res
->u
.group_icon
);
2381 write_rc_menu (e
, res
->u
.menu
, menuex
);
2384 case RES_TYPE_RCDATA
:
2385 write_rc_rcdata (e
, res
->u
.rcdata
, 0);
2388 case RES_TYPE_STRINGTABLE
:
2389 write_rc_stringtable (e
, name
, res
->u
.stringtable
);
2392 case RES_TYPE_USERDATA
:
2393 write_rc_rcdata (e
, res
->u
.userdata
, 0);
2396 case RES_TYPE_TOOLBAR
:
2397 write_rc_toolbar (e
, res
->u
.toolbar
);
2400 case RES_TYPE_VERSIONINFO
:
2401 write_rc_versioninfo (e
, res
->u
.versioninfo
);
2404 case RES_TYPE_BITMAP
:
2407 write_rc_datablock (e
, res
->u
.data
.length
, res
->u
.data
.data
, 0, 1, 0);
2409 case RES_TYPE_MESSAGETABLE
:
2410 write_rc_messagetable (e
, res
->u
.data
.length
, res
->u
.data
.data
);
2415 /* Write out accelerator information. */
2418 write_rc_accelerators (FILE *e
, const rc_accelerator
*accelerators
)
2420 const rc_accelerator
*acc
;
2422 fprintf (e
, "BEGIN\n");
2423 for (acc
= accelerators
; acc
!= NULL
; acc
= acc
->next
)
2429 if ((acc
->key
& 0x7f) == acc
->key
2430 && ISPRINT (acc
->key
)
2431 && (acc
->flags
& ACC_VIRTKEY
) == 0)
2433 fprintf (e
, "\"%c\"", (char) acc
->key
);
2438 fprintf (e
, "%d", (int) acc
->key
);
2442 fprintf (e
, ", %d", (int) acc
->id
);
2446 if ((acc
->flags
& ACC_VIRTKEY
) != 0)
2447 fprintf (e
, ", VIRTKEY");
2449 fprintf (e
, ", ASCII");
2452 if ((acc
->flags
& ACC_SHIFT
) != 0)
2453 fprintf (e
, ", SHIFT");
2454 if ((acc
->flags
& ACC_CONTROL
) != 0)
2455 fprintf (e
, ", CONTROL");
2456 if ((acc
->flags
& ACC_ALT
) != 0)
2457 fprintf (e
, ", ALT");
2462 fprintf (e
, "END\n");
2465 /* Write out cursor information. This would normally be in a separate
2466 file, which the rc file would include. */
2469 write_rc_cursor (FILE *e
, const rc_cursor
*cursor
)
2471 fprintf (e
, "BEGIN\n");
2473 fprintf (e
, " 0x%x, 0x%x,\t/* Hotspot x: %d, y: %d. */\n",
2474 (unsigned int) cursor
->xhotspot
, (unsigned int) cursor
->yhotspot
,
2475 (int) cursor
->xhotspot
, (int) cursor
->yhotspot
);
2476 write_rc_datablock (e
, (rc_uint_type
) cursor
->length
, (const bfd_byte
*) cursor
->data
,
2478 fprintf (e
, "END\n");
2481 /* Write out group cursor data. This would normally be built from the
2485 write_rc_group_cursor (FILE *e
, const rc_group_cursor
*group_cursor
)
2487 const rc_group_cursor
*gc
;
2490 for (c
= 0, gc
= group_cursor
; gc
!= NULL
; gc
= gc
->next
, c
++)
2492 fprintf (e
, "BEGIN\n");
2495 fprintf (e
, "0, 2, %d%s\t /* Having %d items. */\n", c
, (c
!= 0 ? "," : ""), c
);
2497 fprintf (e
, "/* width, height, planes, bits, bytes, index. */\n");
2499 for (c
= 1, gc
= group_cursor
; gc
!= NULL
; gc
= gc
->next
, c
++)
2502 fprintf (e
, "%d, %d, %d, %d, 0x%xL, %d%s /* Element %d. */\n",
2503 (int) gc
->width
, (int) gc
->height
, (int) gc
->planes
, (int) gc
->bits
,
2504 (unsigned int) gc
->bytes
, (int) gc
->index
, (gc
->next
!= NULL
? "," : ""), c
);
2505 fprintf (e
, "/* width: %d; height %d; planes %d; bits %d. */\n",
2506 (int) gc
->width
, (int) gc
->height
, (int) gc
->planes
,
2509 fprintf (e
, "END\n");
2512 /* Write dialog data. */
2515 write_rc_dialog (FILE *e
, const rc_dialog
*dialog
)
2517 const rc_dialog_control
*control
;
2519 fprintf (e
, "STYLE 0x%x\n", dialog
->style
);
2521 if (dialog
->exstyle
!= 0)
2522 fprintf (e
, "EXSTYLE 0x%x\n", (unsigned int) dialog
->exstyle
);
2524 if ((dialog
->class.named
&& dialog
->class.u
.n
.length
> 0)
2525 || dialog
->class.u
.id
!= 0)
2527 fprintf (e
, "CLASS ");
2528 res_id_print (e
, dialog
->class, 1);
2532 if (dialog
->caption
!= NULL
)
2534 fprintf (e
, "CAPTION ");
2535 unicode_print_quoted (e
, dialog
->caption
, -1);
2539 if ((dialog
->menu
.named
&& dialog
->menu
.u
.n
.length
> 0)
2540 || dialog
->menu
.u
.id
!= 0)
2542 fprintf (e
, "MENU ");
2543 res_id_print (e
, dialog
->menu
, 0);
2547 if (dialog
->font
!= NULL
)
2549 fprintf (e
, "FONT %d, ", (int) dialog
->pointsize
);
2550 unicode_print_quoted (e
, dialog
->font
, -1);
2551 if (dialog
->ex
!= NULL
2552 && (dialog
->ex
->weight
!= 0
2553 || dialog
->ex
->italic
!= 0
2554 || dialog
->ex
->charset
!= 1))
2555 fprintf (e
, ", %d, %d, %d",
2556 (int) dialog
->ex
->weight
,
2557 (int) dialog
->ex
->italic
,
2558 (int) dialog
->ex
->charset
);
2562 fprintf (e
, "BEGIN\n");
2564 for (control
= dialog
->controls
; control
!= NULL
; control
= control
->next
)
2565 write_rc_dialog_control (e
, control
);
2567 fprintf (e
, "END\n");
2570 /* For each predefined control keyword, this table provides the class
2576 unsigned short class;
2577 unsigned long style
;
2580 static const struct control_info control_info
[] =
2582 { "AUTO3STATE", CTL_BUTTON
, BS_AUTO3STATE
},
2583 { "AUTOCHECKBOX", CTL_BUTTON
, BS_AUTOCHECKBOX
},
2584 { "AUTORADIOBUTTON", CTL_BUTTON
, BS_AUTORADIOBUTTON
},
2585 { "CHECKBOX", CTL_BUTTON
, BS_CHECKBOX
},
2586 { "COMBOBOX", CTL_COMBOBOX
, (unsigned long) -1 },
2587 { "CTEXT", CTL_STATIC
, SS_CENTER
},
2588 { "DEFPUSHBUTTON", CTL_BUTTON
, BS_DEFPUSHBUTTON
},
2589 { "EDITTEXT", CTL_EDIT
, (unsigned long) -1 },
2590 { "GROUPBOX", CTL_BUTTON
, BS_GROUPBOX
},
2591 { "ICON", CTL_STATIC
, SS_ICON
},
2592 { "LISTBOX", CTL_LISTBOX
, (unsigned long) -1 },
2593 { "LTEXT", CTL_STATIC
, SS_LEFT
},
2594 { "PUSHBOX", CTL_BUTTON
, BS_PUSHBOX
},
2595 { "PUSHBUTTON", CTL_BUTTON
, BS_PUSHBUTTON
},
2596 { "RADIOBUTTON", CTL_BUTTON
, BS_RADIOBUTTON
},
2597 { "RTEXT", CTL_STATIC
, SS_RIGHT
},
2598 { "SCROLLBAR", CTL_SCROLLBAR
, (unsigned long) -1 },
2599 { "STATE3", CTL_BUTTON
, BS_3STATE
},
2600 /* It's important that USERBUTTON come after all the other button
2601 types, so that it won't be matched too early. */
2602 { "USERBUTTON", CTL_BUTTON
, (unsigned long) -1 },
2606 /* Write a dialog control. */
2609 write_rc_dialog_control (FILE *e
, const rc_dialog_control
*control
)
2611 const struct control_info
*ci
;
2615 if (control
->class.named
)
2619 for (ci
= control_info
; ci
->name
!= NULL
; ++ci
)
2620 if (ci
->class == control
->class.u
.id
2621 && (ci
->style
== (unsigned long) -1
2622 || ci
->style
== (control
->style
& 0xff)))
2626 fprintf (e
, "CONTROL");
2627 else if (ci
->name
!= NULL
)
2628 fprintf (e
, "%s", ci
->name
);
2631 fprintf (e
, "CONTROL");
2635 if (control
->text
.named
|| control
->text
.u
.id
!= 0)
2638 res_id_print (e
, control
->text
, 1);
2642 fprintf (e
, " %d, ", (int) control
->id
);
2646 if (control
->class.named
)
2648 res_id_print (e
, control
->class, 0);
2649 if (control
->class.named
)
2651 fprintf (e
, ", 0x%x, ", (unsigned int) control
->style
);
2654 fprintf (e
, "%d, %d", (int) control
->x
, (int) control
->y
);
2656 if (control
->style
!= SS_ICON
2657 || control
->exstyle
!= 0
2658 || control
->width
!= 0
2659 || control
->height
!= 0
2660 || control
->help
!= 0)
2662 fprintf (e
, ", %d, %d", (int) control
->width
, (int) control
->height
);
2664 /* FIXME: We don't need to print the style if it is the default.
2665 More importantly, in certain cases we actually need to turn
2666 off parts of the forced style, by using NOT. */
2668 fprintf (e
, ", 0x%x", (unsigned int) control
->style
);
2670 if (control
->exstyle
!= 0 || control
->help
!= 0)
2671 fprintf (e
, ", 0x%x, %u", (unsigned int) control
->exstyle
,
2672 (unsigned int) control
->help
);
2677 if (control
->data
!= NULL
)
2678 write_rc_rcdata (e
, control
->data
, 2);
2681 /* Write out font directory data. This would normally be built from
2685 write_rc_fontdir (FILE *e
, const rc_fontdir
*fontdir
)
2687 const rc_fontdir
*fc
;
2690 for (c
= 0, fc
= fontdir
; fc
!= NULL
; fc
= fc
->next
, c
++)
2692 fprintf (e
, "BEGIN\n");
2694 fprintf (e
, "%d%s\t /* Has %d elements. */\n", c
, (c
!= 0 ? "," : ""), c
);
2695 for (c
= 1, fc
= fontdir
; fc
!= NULL
; fc
= fc
->next
, c
++)
2698 fprintf (e
, "%d,\t/* Font no %d with index %d. */\n",
2699 (int) fc
->index
, c
, (int) fc
->index
);
2700 write_rc_datablock (e
, (rc_uint_type
) fc
->length
- 2,
2701 (const bfd_byte
*) fc
->data
+ 4,fc
->next
!= NULL
,
2704 fprintf (e
, "END\n");
2707 /* Write out group icon data. This would normally be built from the
2711 write_rc_group_icon (FILE *e
, const rc_group_icon
*group_icon
)
2713 const rc_group_icon
*gi
;
2716 for (c
= 0, gi
= group_icon
; gi
!= NULL
; gi
= gi
->next
, c
++)
2719 fprintf (e
, "BEGIN\n");
2721 fprintf (e
, " 0, 1, %d%s\t /* Has %d elements. */\n", c
, (c
!= 0 ? "," : ""), c
);
2724 fprintf (e
, "/* \"width height colors pad\", planes, bits, bytes, index. */\n");
2725 for (c
= 1, gi
= group_icon
; gi
!= NULL
; gi
= gi
->next
, c
++)
2728 fprintf (e
, "\"\\%03o\\%03o\\%03o\\%03o\", %d, %d, 0x%xL, %d%s\t/* Element no %d. */\n",
2729 gi
->width
, gi
->height
, gi
->colors
, 0, (int) gi
->planes
, (int) gi
->bits
,
2730 (unsigned int) gi
->bytes
, (int) gi
->index
, (gi
->next
!= NULL
? "," : ""), c
);
2732 fprintf (e
, "END\n");
2735 /* Write out a menu resource. */
2738 write_rc_menu (FILE *e
, const rc_menu
*menu
, int menuex
)
2740 if (menu
->help
!= 0)
2741 fprintf (e
, "// Help ID: %u\n", (unsigned int) menu
->help
);
2742 write_rc_menuitems (e
, menu
->items
, menuex
, 0);
2746 write_rc_toolbar (FILE *e
, const rc_toolbar
*tb
)
2748 rc_toolbar_item
*it
;
2750 fprintf (e
, "BEGIN\n");
2755 if (it
->id
.u
.id
== 0)
2756 fprintf (e
, "SEPARATOR\n");
2758 fprintf (e
, "BUTTON %d\n", (int) it
->id
.u
.id
);
2762 fprintf (e
, "END\n");
2765 /* Write out menuitems. */
2768 write_rc_menuitems (FILE *e
, const rc_menuitem
*menuitems
, int menuex
,
2771 const rc_menuitem
*mi
;
2774 fprintf (e
, "BEGIN\n");
2776 for (mi
= menuitems
; mi
!= NULL
; mi
= mi
->next
)
2778 indent (e
, ind
+ 2);
2780 if (mi
->popup
== NULL
)
2781 fprintf (e
, "MENUITEM");
2783 fprintf (e
, "POPUP");
2786 && mi
->popup
== NULL
2791 fprintf (e
, " SEPARATOR\n");
2795 if (mi
->text
== NULL
)
2796 fprintf (e
, " \"\"");
2800 unicode_print_quoted (e
, mi
->text
, -1);
2805 if (mi
->popup
== NULL
)
2806 fprintf (e
, ", %d", (int) mi
->id
);
2808 if ((mi
->type
& MENUITEM_CHECKED
) != 0)
2809 fprintf (e
, ", CHECKED");
2810 if ((mi
->type
& MENUITEM_GRAYED
) != 0)
2811 fprintf (e
, ", GRAYED");
2812 if ((mi
->type
& MENUITEM_HELP
) != 0)
2813 fprintf (e
, ", HELP");
2814 if ((mi
->type
& MENUITEM_INACTIVE
) != 0)
2815 fprintf (e
, ", INACTIVE");
2816 if ((mi
->type
& MENUITEM_MENUBARBREAK
) != 0)
2817 fprintf (e
, ", MENUBARBREAK");
2818 if ((mi
->type
& MENUITEM_MENUBREAK
) != 0)
2819 fprintf (e
, ", MENUBREAK");
2823 if (mi
->id
!= 0 || mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2825 fprintf (e
, ", %d", (int) mi
->id
);
2826 if (mi
->type
!= 0 || mi
->state
!= 0 || mi
->help
!= 0)
2828 fprintf (e
, ", %u", (unsigned int) mi
->type
);
2829 if (mi
->state
!= 0 || mi
->help
!= 0)
2831 fprintf (e
, ", %u", (unsigned int) mi
->state
);
2833 fprintf (e
, ", %u", (unsigned int) mi
->help
);
2841 if (mi
->popup
!= NULL
)
2842 write_rc_menuitems (e
, mi
->popup
, menuex
, ind
+ 2);
2846 fprintf (e
, "END\n");
2850 test_rc_datablock_unicode (rc_uint_type length
, const bfd_byte
*data
)
2853 if ((length
& 1) != 0)
2856 for (i
= 0; i
< length
; i
+= 2)
2858 if (data
[i
] == 0 && data
[i
+ 1] == 0 && (i
+ 2) < length
)
2860 if (data
[i
] == 0xff && data
[i
+ 1] == 0xff)
2867 test_rc_datablock_text (rc_uint_type length
, const bfd_byte
*data
)
2877 for (i
= 0, c
= 0; i
< length
; i
++)
2879 if (! ISPRINT (data
[i
]) && data
[i
] != '\n'
2880 && ! (data
[i
] == '\r' && (i
+ 1) < length
&& data
[i
+ 1] == '\n')
2882 && ! (data
[i
] == 0 && (i
+ 1) != length
))
2888 else if (data
[i
] == '\n') has_nl
++;
2890 if (length
> 80 && ! has_nl
)
2892 c
= (((c
* 10000) + (i
/ 100) - 1)) / i
;
2899 write_rc_messagetable (FILE *e
, rc_uint_type length
, const bfd_byte
*data
)
2902 const struct bin_messagetable
*mt
;
2903 fprintf (e
, "BEGIN\n");
2905 write_rc_datablock (e
, length
, data
, 0, 0, 0);
2908 wr_printcomment (e
, "MC syntax dump");
2909 if (length
< BIN_MESSAGETABLE_SIZE
)
2914 mt
= (const struct bin_messagetable
*) data
;
2915 m
= windres_get_32 (&wrtarget
, mt
->cblocks
, length
);
2916 if (length
< (BIN_MESSAGETABLE_SIZE
+ m
* BIN_MESSAGETABLE_BLOCK_SIZE
))
2921 for (i
= 0; i
< m
; i
++)
2923 rc_uint_type low
, high
, offset
;
2924 const struct bin_messagetable_item
*mti
;
2926 low
= windres_get_32 (&wrtarget
, mt
->items
[i
].lowid
, 4);
2927 high
= windres_get_32 (&wrtarget
, mt
->items
[i
].highid
, 4);
2928 offset
= windres_get_32 (&wrtarget
, mt
->items
[i
].offset
, 4);
2931 rc_uint_type elen
, flags
;
2932 if ((offset
+ BIN_MESSAGETABLE_ITEM_SIZE
) > length
)
2937 mti
= (const struct bin_messagetable_item
*) &data
[offset
];
2938 elen
= windres_get_16 (&wrtarget
, mti
->length
, 2);
2939 flags
= windres_get_16 (&wrtarget
, mti
->flags
, 2);
2940 if ((offset
+ elen
) > length
)
2945 wr_printcomment (e
, "MessageId = 0x%x", low
);
2946 wr_printcomment (e
, "");
2947 if ((flags
& MESSAGE_RESOURCE_UNICODE
) == MESSAGE_RESOURCE_UNICODE
)
2948 unicode_print (e
, (const unichar
*) mti
->data
,
2949 (elen
- BIN_MESSAGETABLE_ITEM_SIZE
) / 2);
2951 ascii_print (e
, (const char *) mti
->data
,
2952 (elen
- BIN_MESSAGETABLE_ITEM_SIZE
));
2953 wr_printcomment (e
,"");
2960 wr_printcomment (e
, "Illegal data");
2962 fprintf (e
, "END\n");
2966 write_rc_datablock (FILE *e
, rc_uint_type length
, const bfd_byte
*data
, int has_next
,
2967 int hasblock
, int show_comment
)
2972 fprintf (e
, "BEGIN\n");
2974 if (show_comment
== -1)
2976 if (test_rc_datablock_text(length
, data
))
2979 for (i
= 0; i
< length
;)
2984 for (c
= 0; i
< length
&& c
< 160 && data
[i
] != '\n'; c
++, i
++)
2986 if (i
< length
&& data
[i
] == '\n')
2988 ascii_print (e
, (const char *) &data
[i
- c
], c
);
2997 fprintf (e
, "\"\"");
3003 fprintf (e
, "END\n");
3006 if (test_rc_datablock_unicode (length
, data
))
3009 for (i
= 0; i
< length
;)
3013 u
= (const unichar
*) &data
[i
];
3017 for (c
= 0; i
< length
&& c
< 160 && u
[c
] != '\n'; c
++, i
+= 2)
3019 if (i
< length
&& u
[c
] == '\n')
3021 unicode_print (e
, u
, c
);
3030 fprintf (e
, "L\"\"");
3036 fprintf (e
, "END\n");
3045 rc_uint_type i
, max_row
;
3048 max_row
= (show_comment
? 4 : 8);
3050 for (i
= 0; i
+ 3 < length
;)
3053 rc_uint_type comment_start
;
3060 for (k
= 0; k
< max_row
&& i
+ 3 < length
; k
++, i
+= 4)
3063 plen
= fprintf (e
, "0x%lxL",
3064 (long) windres_get_32 (&wrtarget
, data
+ i
, length
- i
));
3066 plen
= fprintf (e
, " 0x%lxL",
3067 (long) windres_get_32 (&wrtarget
, data
+ i
, length
- i
)) - 1;
3068 if (has_next
|| (i
+ 4) < length
)
3070 if (plen
>0 && plen
< 11)
3071 indent (e
, 11 - plen
);
3077 fprintf (e
, "\t/* ");
3078 ascii_print (e
, (const char *) &data
[comment_start
], i
- comment_start
);
3079 fprintf (e
, ". */");
3089 plen
= fprintf (e
, "0x%x",
3090 (int) windres_get_16 (&wrtarget
, data
+ i
, length
- i
));
3091 if (has_next
|| i
+ 2 < length
)
3093 if (plen
> 0 && plen
< 11)
3094 indent (e
, 11 - plen
);
3099 fprintf (e
, "\t/* ");
3100 ascii_print (e
, (const char *) &data
[i
], 2);
3101 fprintf (e
, ". */");
3113 ascii_print (e
, (const char *) &data
[i
], 1);
3122 fprintf (e
, "END\n");
3125 /* Write out an rcdata resource. This is also used for other types of
3126 resources that need to print arbitrary data. */
3129 write_rc_rcdata (FILE *e
, const rc_rcdata_item
*rcdata
, int ind
)
3131 const rc_rcdata_item
*ri
;
3134 fprintf (e
, "BEGIN\n");
3136 for (ri
= rcdata
; ri
!= NULL
; ri
= ri
->next
)
3138 if (ri
->type
== RCDATA_BUFFER
&& ri
->u
.buffer
.length
== 0)
3147 indent (e
, ind
+ 2);
3148 fprintf (e
, "%ld", (long) (ri
->u
.word
& 0xffff));
3152 indent (e
, ind
+ 2);
3153 fprintf (e
, "%luL", (unsigned long) ri
->u
.dword
);
3157 indent (e
, ind
+ 2);
3159 ascii_print (e
, ri
->u
.string
.s
, ri
->u
.string
.length
);
3163 case RCDATA_WSTRING
:
3164 indent (e
, ind
+ 2);
3166 unicode_print (e
, ri
->u
.wstring
.w
, ri
->u
.wstring
.length
);
3171 write_rc_datablock (e
, (rc_uint_type
) ri
->u
.buffer
.length
,
3172 (const bfd_byte
*) ri
->u
.buffer
.data
,
3173 ri
->next
!= NULL
, 0, -1);
3177 if (ri
->type
!= RCDATA_BUFFER
)
3179 if (ri
->next
!= NULL
)
3186 fprintf (e
, "END\n");
3189 /* Write out a stringtable resource. */
3192 write_rc_stringtable (FILE *e
, const rc_res_id
*name
,
3193 const rc_stringtable
*stringtable
)
3195 rc_uint_type offset
;
3198 if (name
!= NULL
&& ! name
->named
)
3199 offset
= (name
->u
.id
- 1) << 4;
3202 fprintf (e
, "/* %s string table name. */\n",
3203 name
== NULL
? "Missing" : "Invalid");
3207 fprintf (e
, "BEGIN\n");
3209 for (i
= 0; i
< 16; i
++)
3211 if (stringtable
->strings
[i
].length
!= 0)
3213 fprintf (e
, " %lu, ", (long) offset
+ i
);
3214 unicode_print_quoted (e
, stringtable
->strings
[i
].string
,
3215 stringtable
->strings
[i
].length
);
3220 fprintf (e
, "END\n");
3223 /* Write out a versioninfo resource. */
3226 write_rc_versioninfo (FILE *e
, const rc_versioninfo
*versioninfo
)
3228 const rc_fixed_versioninfo
*f
;
3229 const rc_ver_info
*vi
;
3231 f
= versioninfo
->fixed
;
3232 if (f
->file_version_ms
!= 0 || f
->file_version_ls
!= 0)
3233 fprintf (e
, " FILEVERSION %u, %u, %u, %u\n",
3234 (unsigned int) ((f
->file_version_ms
>> 16) & 0xffff),
3235 (unsigned int) (f
->file_version_ms
& 0xffff),
3236 (unsigned int) ((f
->file_version_ls
>> 16) & 0xffff),
3237 (unsigned int) (f
->file_version_ls
& 0xffff));
3238 if (f
->product_version_ms
!= 0 || f
->product_version_ls
!= 0)
3239 fprintf (e
, " PRODUCTVERSION %u, %u, %u, %u\n",
3240 (unsigned int) ((f
->product_version_ms
>> 16) & 0xffff),
3241 (unsigned int) (f
->product_version_ms
& 0xffff),
3242 (unsigned int) ((f
->product_version_ls
>> 16) & 0xffff),
3243 (unsigned int) (f
->product_version_ls
& 0xffff));
3244 if (f
->file_flags_mask
!= 0)
3245 fprintf (e
, " FILEFLAGSMASK 0x%x\n", (unsigned int) f
->file_flags_mask
);
3246 if (f
->file_flags
!= 0)
3247 fprintf (e
, " FILEFLAGS 0x%x\n", (unsigned int) f
->file_flags
);
3248 if (f
->file_os
!= 0)
3249 fprintf (e
, " FILEOS 0x%x\n", (unsigned int) f
->file_os
);
3250 if (f
->file_type
!= 0)
3251 fprintf (e
, " FILETYPE 0x%x\n", (unsigned int) f
->file_type
);
3252 if (f
->file_subtype
!= 0)
3253 fprintf (e
, " FILESUBTYPE 0x%x\n", (unsigned int) f
->file_subtype
);
3254 if (f
->file_date_ms
!= 0 || f
->file_date_ls
!= 0)
3255 fprintf (e
, "/* Date: %u, %u. */\n",
3256 (unsigned int) f
->file_date_ms
, (unsigned int) f
->file_date_ls
);
3258 fprintf (e
, "BEGIN\n");
3260 for (vi
= versioninfo
->var
; vi
!= NULL
; vi
= vi
->next
)
3264 case VERINFO_STRING
:
3266 const rc_ver_stringinfo
*vs
;
3268 fprintf (e
, " BLOCK \"StringFileInfo\"\n");
3269 fprintf (e
, " BEGIN\n");
3270 fprintf (e
, " BLOCK ");
3271 unicode_print_quoted (e
, vi
->u
.string
.language
, -1);
3273 fprintf (e
, " BEGIN\n");
3275 for (vs
= vi
->u
.string
.strings
; vs
!= NULL
; vs
= vs
->next
)
3277 fprintf (e
, " VALUE ");
3278 unicode_print_quoted (e
, vs
->key
, -1);
3280 unicode_print_quoted (e
, vs
->value
, -1);
3284 fprintf (e
, " END\n");
3285 fprintf (e
, " END\n");
3291 const rc_ver_varinfo
*vv
;
3293 fprintf (e
, " BLOCK \"VarFileInfo\"\n");
3294 fprintf (e
, " BEGIN\n");
3295 fprintf (e
, " VALUE ");
3296 unicode_print_quoted (e
, vi
->u
.var
.key
, -1);
3298 for (vv
= vi
->u
.var
.var
; vv
!= NULL
; vv
= vv
->next
)
3299 fprintf (e
, ", 0x%x, %d", (unsigned int) vv
->language
,
3302 fprintf (e
, "\n END\n");
3309 fprintf (e
, "END\n");
3313 rcdata_copy (const rc_rcdata_item
*src
, bfd_byte
*dst
)
3321 windres_put_16 (&wrtarget
, dst
, (rc_uint_type
) src
->u
.word
);
3325 windres_put_32 (&wrtarget
, dst
, (rc_uint_type
) src
->u
.dword
);
3328 if (dst
&& src
->u
.string
.length
)
3329 memcpy (dst
, src
->u
.string
.s
, src
->u
.string
.length
);
3330 return (rc_uint_type
) src
->u
.string
.length
;
3331 case RCDATA_WSTRING
:
3332 if (dst
&& src
->u
.wstring
.length
)
3333 memcpy (dst
, src
->u
.wstring
.w
, src
->u
.wstring
.length
* sizeof (unichar
));
3334 return (rc_uint_type
) (src
->u
.wstring
.length
* sizeof (unichar
));
3336 if (dst
&& src
->u
.buffer
.length
)
3337 memcpy (dst
, src
->u
.buffer
.data
, src
->u
.buffer
.length
);
3338 return (rc_uint_type
) src
->u
.buffer
.length
;
3342 /* Never reached. */