file config.texi was initially added on branch binutils-2_17-branch.
[binutils.git] / binutils / resrc.c
blob73b482cd04ab6ffe8210a68bbe0ae5845327b104
1 /* resrc.c -- read and write Windows rc files.
2 Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005
3 Free Software Foundation, Inc.
4 Written by Ian Lance Taylor, Cygnus Support.
6 This file is part of GNU Binutils.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
21 02110-1301, USA. */
23 /* This file contains functions that read and write Windows rc files.
24 These are text files that represent resources. */
26 #include "bfd.h"
27 #include "bucomm.h"
28 #include "libiberty.h"
29 #include "safe-ctype.h"
30 #include "windres.h"
32 #include <assert.h>
33 #include <errno.h>
34 #include <sys/stat.h>
35 #ifdef HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif
39 #ifdef HAVE_SYS_WAIT_H
40 #include <sys/wait.h>
41 #else /* ! HAVE_SYS_WAIT_H */
42 #if ! defined (_WIN32) || defined (__CYGWIN__)
43 #ifndef WIFEXITED
44 #define WIFEXITED(w) (((w)&0377) == 0)
45 #endif
46 #ifndef WIFSIGNALED
47 #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
48 #endif
49 #ifndef WTERMSIG
50 #define WTERMSIG(w) ((w) & 0177)
51 #endif
52 #ifndef WEXITSTATUS
53 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
54 #endif
55 #else /* defined (_WIN32) && ! defined (__CYGWIN__) */
56 #ifndef WIFEXITED
57 #define WIFEXITED(w) (((w) & 0xff) == 0)
58 #endif
59 #ifndef WIFSIGNALED
60 #define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
61 #endif
62 #ifndef WTERMSIG
63 #define WTERMSIG(w) ((w) & 0x7f)
64 #endif
65 #ifndef WEXITSTATUS
66 #define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
67 #endif
68 #endif /* defined (_WIN32) && ! defined (__CYGWIN__) */
69 #endif /* ! HAVE_SYS_WAIT_H */
71 #ifndef STDOUT_FILENO
72 #define STDOUT_FILENO 1
73 #endif
75 #if defined (_WIN32) && ! defined (__CYGWIN__)
76 #define popen _popen
77 #define pclose _pclose
78 #endif
80 /* The default preprocessor. */
82 #define DEFAULT_PREPROCESSOR "gcc -E -xc -DRC_INVOKED"
84 /* We read the directory entries in a cursor or icon file into
85 instances of this structure. */
87 struct icondir
89 /* Width of image. */
90 unsigned char width;
91 /* Height of image. */
92 unsigned char height;
93 /* Number of colors in image. */
94 unsigned char colorcount;
95 union
97 struct
99 /* Color planes. */
100 unsigned short planes;
101 /* Bits per pixel. */
102 unsigned short bits;
103 } icon;
104 struct
106 /* X coordinate of hotspot. */
107 unsigned short xhotspot;
108 /* Y coordinate of hotspot. */
109 unsigned short yhotspot;
110 } cursor;
111 } u;
112 /* Bytes in image. */
113 unsigned long bytes;
114 /* File offset of image. */
115 unsigned long offset;
118 /* The name of the rc file we are reading. */
120 char *rc_filename;
122 /* The line number in the rc file. */
124 int rc_lineno;
126 /* The pipe we are reading from, so that we can close it if we exit. */
128 static FILE *cpp_pipe;
130 /* The temporary file used if we're not using popen, so we can delete it
131 if we exit. */
133 static char *cpp_temp_file;
135 /* Input stream is either a file or a pipe. */
137 static enum {ISTREAM_PIPE, ISTREAM_FILE} istream_type;
139 /* As we read the rc file, we attach information to this structure. */
141 static struct res_directory *resources;
143 /* The number of cursor resources we have written out. */
145 static int cursors;
147 /* The number of font resources we have written out. */
149 static int fonts;
151 /* Font directory information. */
153 struct fontdir *fontdirs;
155 /* Resource info to use for fontdirs. */
157 struct res_res_info fontdirs_resinfo;
159 /* The number of icon resources we have written out. */
161 static int icons;
163 /* Local functions. */
165 static int run_cmd (char *, const char *);
166 static FILE *open_input_stream (char *);
167 static FILE *look_for_default
168 (char *, const char *, int, const char *, const char *);
169 static void close_input_stream (void);
170 static void unexpected_eof (const char *);
171 static int get_word (FILE *, const char *);
172 static unsigned long get_long (FILE *, const char *);
173 static void get_data (FILE *, unsigned char *, unsigned long, const char *);
174 static void define_fontdirs (void);
176 /* Run `cmd' and redirect the output to `redir'. */
178 static int
179 run_cmd (char *cmd, const char *redir)
181 char *s;
182 int pid, wait_status, retcode;
183 int i;
184 const char **argv;
185 char *errmsg_fmt, *errmsg_arg;
186 char *temp_base = choose_temp_base ();
187 int in_quote;
188 char sep;
189 int redir_handle = -1;
190 int stdout_save = -1;
192 /* Count the args. */
193 i = 0;
195 for (s = cmd; *s; s++)
196 if (*s == ' ')
197 i++;
199 i++;
200 argv = alloca (sizeof (char *) * (i + 3));
201 i = 0;
202 s = cmd;
204 while (1)
206 while (*s == ' ' && *s != 0)
207 s++;
209 if (*s == 0)
210 break;
212 in_quote = (*s == '\'' || *s == '"');
213 sep = (in_quote) ? *s++ : ' ';
214 argv[i++] = s;
216 while (*s != sep && *s != 0)
217 s++;
219 if (*s == 0)
220 break;
222 *s++ = 0;
224 if (in_quote)
225 s++;
227 argv[i++] = NULL;
229 /* Setup the redirection. We can't use the usual fork/exec and redirect
230 since we may be running on non-POSIX Windows host. */
232 fflush (stdout);
233 fflush (stderr);
235 /* Open temporary output file. */
236 redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT, 0666);
237 if (redir_handle == -1)
238 fatal (_("can't open temporary file `%s': %s"), redir,
239 strerror (errno));
241 /* Duplicate the stdout file handle so it can be restored later. */
242 stdout_save = dup (STDOUT_FILENO);
243 if (stdout_save == -1)
244 fatal (_("can't redirect stdout: `%s': %s"), redir, strerror (errno));
246 /* Redirect stdout to our output file. */
247 dup2 (redir_handle, STDOUT_FILENO);
249 pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
250 &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
252 /* Restore stdout to its previous setting. */
253 dup2 (stdout_save, STDOUT_FILENO);
255 /* Close response file. */
256 close (redir_handle);
258 if (pid == -1)
260 fatal (_("%s %s: %s"), errmsg_fmt, errmsg_arg, strerror (errno));
261 return 1;
264 retcode = 0;
265 pid = pwait (pid, &wait_status, 0);
267 if (pid == -1)
269 fatal (_("wait: %s"), strerror (errno));
270 retcode = 1;
272 else if (WIFSIGNALED (wait_status))
274 fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
275 retcode = 1;
277 else if (WIFEXITED (wait_status))
279 if (WEXITSTATUS (wait_status) != 0)
281 fatal (_("%s exited with status %d"), cmd,
282 WEXITSTATUS (wait_status));
283 retcode = 1;
286 else
287 retcode = 1;
289 return retcode;
292 static FILE *
293 open_input_stream (char *cmd)
295 if (istream_type == ISTREAM_FILE)
297 char *fileprefix;
299 fileprefix = choose_temp_base ();
300 cpp_temp_file = (char *) xmalloc (strlen (fileprefix) + 5);
301 sprintf (cpp_temp_file, "%s.irc", fileprefix);
302 free (fileprefix);
304 if (run_cmd (cmd, cpp_temp_file))
305 fatal (_("can't execute `%s': %s"), cmd, strerror (errno));
307 cpp_pipe = fopen (cpp_temp_file, FOPEN_RT);;
308 if (cpp_pipe == NULL)
309 fatal (_("can't open temporary file `%s': %s"),
310 cpp_temp_file, strerror (errno));
312 if (verbose)
313 fprintf (stderr,
314 _("Using temporary file `%s' to read preprocessor output\n"),
315 cpp_temp_file);
317 else
319 cpp_pipe = popen (cmd, FOPEN_RT);
320 if (cpp_pipe == NULL)
321 fatal (_("can't popen `%s': %s"), cmd, strerror (errno));
322 if (verbose)
323 fprintf (stderr, _("Using popen to read preprocessor output\n"));
326 xatexit (close_input_stream);
327 return cpp_pipe;
330 /* look for the preprocessor program */
332 static FILE *
333 look_for_default (char *cmd, const char *prefix, int end_prefix,
334 const char *preprocargs, const char *filename)
336 char *space;
337 int found;
338 struct stat s;
340 strcpy (cmd, prefix);
342 sprintf (cmd + end_prefix, "%s", DEFAULT_PREPROCESSOR);
343 space = strchr (cmd + end_prefix, ' ');
344 if (space)
345 *space = 0;
347 if (
348 #if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32)
349 strchr (cmd, '\\') ||
350 #endif
351 strchr (cmd, '/'))
353 found = (stat (cmd, &s) == 0
354 #ifdef HAVE_EXECUTABLE_SUFFIX
355 || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
356 #endif
359 if (! found)
361 if (verbose)
362 fprintf (stderr, _("Tried `%s'\n"), cmd);
363 return NULL;
367 strcpy (cmd, prefix);
369 sprintf (cmd + end_prefix, "%s %s %s",
370 DEFAULT_PREPROCESSOR, preprocargs, filename);
372 if (verbose)
373 fprintf (stderr, _("Using `%s'\n"), cmd);
375 cpp_pipe = open_input_stream (cmd);
376 return cpp_pipe;
379 /* Read an rc file. */
381 struct res_directory *
382 read_rc_file (const char *filename, const char *preprocessor,
383 const char *preprocargs, int language, int use_temp_file)
385 char *cmd;
387 istream_type = (use_temp_file) ? ISTREAM_FILE : ISTREAM_PIPE;
389 if (preprocargs == NULL)
390 preprocargs = "";
391 if (filename == NULL)
392 filename = "-";
394 if (preprocessor)
396 cmd = xmalloc (strlen (preprocessor)
397 + strlen (preprocargs)
398 + strlen (filename)
399 + 10);
400 sprintf (cmd, "%s %s %s", preprocessor, preprocargs, filename);
402 cpp_pipe = open_input_stream (cmd);
404 else
406 char *dash, *slash, *cp;
408 preprocessor = DEFAULT_PREPROCESSOR;
410 cmd = xmalloc (strlen (program_name)
411 + strlen (preprocessor)
412 + strlen (preprocargs)
413 + strlen (filename)
414 #ifdef HAVE_EXECUTABLE_SUFFIX
415 + strlen (EXECUTABLE_SUFFIX)
416 #endif
417 + 10);
420 dash = slash = 0;
421 for (cp = program_name; *cp; cp++)
423 if (*cp == '-')
424 dash = cp;
425 if (
426 #if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32)
427 *cp == ':' || *cp == '\\' ||
428 #endif
429 *cp == '/')
431 slash = cp;
432 dash = 0;
436 cpp_pipe = 0;
438 if (dash)
440 /* First, try looking for a prefixed gcc in the windres
441 directory, with the same prefix as windres */
443 cpp_pipe = look_for_default (cmd, program_name, dash-program_name+1,
444 preprocargs, filename);
447 if (slash && !cpp_pipe)
449 /* Next, try looking for a gcc in the same directory as
450 that windres */
452 cpp_pipe = look_for_default (cmd, program_name, slash-program_name+1,
453 preprocargs, filename);
456 if (!cpp_pipe)
458 /* Sigh, try the default */
460 cpp_pipe = look_for_default (cmd, "", 0, preprocargs, filename);
465 free (cmd);
467 rc_filename = xstrdup (filename);
468 rc_lineno = 1;
469 if (language != -1)
470 rcparse_set_language (language);
471 yyin = cpp_pipe;
472 yyparse ();
473 rcparse_discard_strings ();
475 close_input_stream ();
477 if (fontdirs != NULL)
478 define_fontdirs ();
480 free (rc_filename);
481 rc_filename = NULL;
483 return resources;
486 /* Close the input stream if it is open. */
488 static void
489 close_input_stream (void)
491 if (istream_type == ISTREAM_FILE)
493 if (cpp_pipe != NULL)
494 fclose (cpp_pipe);
496 if (cpp_temp_file != NULL)
498 int errno_save = errno;
500 unlink (cpp_temp_file);
501 errno = errno_save;
502 free (cpp_temp_file);
505 else
507 if (cpp_pipe != NULL)
508 pclose (cpp_pipe);
511 /* Since this is also run via xatexit, safeguard. */
512 cpp_pipe = NULL;
513 cpp_temp_file = NULL;
516 /* Report an error while reading an rc file. */
518 void
519 yyerror (const char *msg)
521 fatal ("%s:%d: %s", rc_filename, rc_lineno, msg);
524 /* Issue a warning while reading an rc file. */
526 void
527 rcparse_warning (const char *msg)
529 fprintf (stderr, _("%s:%d: %s\n"), rc_filename, rc_lineno, msg);
532 /* Die if we get an unexpected end of file. */
534 static void
535 unexpected_eof (const char *msg)
537 fatal (_("%s: unexpected EOF"), msg);
540 /* Read a 16 bit word from a file. The data is assumed to be little
541 endian. */
543 static int
544 get_word (FILE *e, const char *msg)
546 int b1, b2;
548 b1 = getc (e);
549 b2 = getc (e);
550 if (feof (e))
551 unexpected_eof (msg);
552 return ((b2 & 0xff) << 8) | (b1 & 0xff);
555 /* Read a 32 bit word from a file. The data is assumed to be little
556 endian. */
558 static unsigned long
559 get_long (FILE *e, const char *msg)
561 int b1, b2, b3, b4;
563 b1 = getc (e);
564 b2 = getc (e);
565 b3 = getc (e);
566 b4 = getc (e);
567 if (feof (e))
568 unexpected_eof (msg);
569 return (((((((b4 & 0xff) << 8)
570 | (b3 & 0xff)) << 8)
571 | (b2 & 0xff)) << 8)
572 | (b1 & 0xff));
575 /* Read data from a file. This is a wrapper to do error checking. */
577 static void
578 get_data (FILE *e, unsigned char *p, unsigned long c, const char *msg)
580 unsigned long got;
582 got = fread (p, 1, c, e);
583 if (got == c)
584 return;
586 fatal (_("%s: read of %lu returned %lu"), msg, c, got);
589 /* Define an accelerator resource. */
591 void
592 define_accelerator (struct res_id id, const struct res_res_info *resinfo,
593 struct accelerator *data)
595 struct res_resource *r;
597 r = define_standard_resource (&resources, RT_ACCELERATOR, id,
598 resinfo->language, 0);
599 r->type = RES_TYPE_ACCELERATOR;
600 r->u.acc = data;
601 r->res_info = *resinfo;
604 /* Define a bitmap resource. Bitmap data is stored in a file. The
605 first 14 bytes of the file are a standard header, which is not
606 included in the resource data. */
608 #define BITMAP_SKIP (14)
610 void
611 define_bitmap (struct res_id id, const struct res_res_info *resinfo,
612 const char *filename)
614 FILE *e;
615 char *real_filename;
616 struct stat s;
617 unsigned char *data;
618 int i;
619 struct res_resource *r;
621 e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename);
623 if (stat (real_filename, &s) < 0)
624 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
625 strerror (errno));
627 data = (unsigned char *) res_alloc (s.st_size - BITMAP_SKIP);
629 for (i = 0; i < BITMAP_SKIP; i++)
630 getc (e);
632 get_data (e, data, s.st_size - BITMAP_SKIP, real_filename);
634 fclose (e);
635 free (real_filename);
637 r = define_standard_resource (&resources, RT_BITMAP, id,
638 resinfo->language, 0);
640 r->type = RES_TYPE_BITMAP;
641 r->u.data.length = s.st_size - BITMAP_SKIP;
642 r->u.data.data = data;
643 r->res_info = *resinfo;
646 /* Define a cursor resource. A cursor file may contain a set of
647 bitmaps, each representing the same cursor at various different
648 resolutions. They each get written out with a different ID. The
649 real cursor resource is then a group resource which can be used to
650 select one of the actual cursors. */
652 void
653 define_cursor (struct res_id id, const struct res_res_info *resinfo,
654 const char *filename)
656 FILE *e;
657 char *real_filename;
658 int type, count, i;
659 struct icondir *icondirs;
660 int first_cursor;
661 struct res_resource *r;
662 struct group_cursor *first, **pp;
664 e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename);
666 /* A cursor file is basically an icon file. The start of the file
667 is a three word structure. The first word is ignored. The
668 second word is the type of data. The third word is the number of
669 entries. */
671 get_word (e, real_filename);
672 type = get_word (e, real_filename);
673 count = get_word (e, real_filename);
674 if (type != 2)
675 fatal (_("cursor file `%s' does not contain cursor data"), real_filename);
677 /* Read in the icon directory entries. */
679 icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
681 for (i = 0; i < count; i++)
683 icondirs[i].width = getc (e);
684 icondirs[i].height = getc (e);
685 icondirs[i].colorcount = getc (e);
686 getc (e);
687 icondirs[i].u.cursor.xhotspot = get_word (e, real_filename);
688 icondirs[i].u.cursor.yhotspot = get_word (e, real_filename);
689 icondirs[i].bytes = get_long (e, real_filename);
690 icondirs[i].offset = get_long (e, real_filename);
692 if (feof (e))
693 unexpected_eof (real_filename);
696 /* Define each cursor as a unique resource. */
698 first_cursor = cursors;
700 for (i = 0; i < count; i++)
702 unsigned char *data;
703 struct res_id name;
704 struct cursor *c;
706 if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
707 fatal (_("%s: fseek to %lu failed: %s"), real_filename,
708 icondirs[i].offset, strerror (errno));
710 data = (unsigned char *) res_alloc (icondirs[i].bytes);
712 get_data (e, data, icondirs[i].bytes, real_filename);
714 c = (struct cursor *) res_alloc (sizeof *c);
715 c->xhotspot = icondirs[i].u.cursor.xhotspot;
716 c->yhotspot = icondirs[i].u.cursor.yhotspot;
717 c->length = icondirs[i].bytes;
718 c->data = data;
720 ++cursors;
722 name.named = 0;
723 name.u.id = cursors;
725 r = define_standard_resource (&resources, RT_CURSOR, name,
726 resinfo->language, 0);
727 r->type = RES_TYPE_CURSOR;
728 r->u.cursor = c;
729 r->res_info = *resinfo;
732 fclose (e);
733 free (real_filename);
735 /* Define a cursor group resource. */
737 first = NULL;
738 pp = &first;
739 for (i = 0; i < count; i++)
741 struct group_cursor *cg;
743 cg = (struct group_cursor *) res_alloc (sizeof *cg);
744 cg->next = NULL;
745 cg->width = icondirs[i].width;
746 cg->height = 2 * icondirs[i].height;
748 /* FIXME: What should these be set to? */
749 cg->planes = 1;
750 cg->bits = 1;
752 cg->bytes = icondirs[i].bytes + 4;
753 cg->index = first_cursor + i + 1;
755 *pp = cg;
756 pp = &(*pp)->next;
759 free (icondirs);
761 r = define_standard_resource (&resources, RT_GROUP_CURSOR, id,
762 resinfo->language, 0);
763 r->type = RES_TYPE_GROUP_CURSOR;
764 r->u.group_cursor = first;
765 r->res_info = *resinfo;
768 /* Define a dialog resource. */
770 void
771 define_dialog (struct res_id id, const struct res_res_info *resinfo,
772 const struct dialog *dialog)
774 struct dialog *copy;
775 struct res_resource *r;
777 copy = (struct dialog *) res_alloc (sizeof *copy);
778 *copy = *dialog;
780 r = define_standard_resource (&resources, RT_DIALOG, id,
781 resinfo->language, 0);
782 r->type = RES_TYPE_DIALOG;
783 r->u.dialog = copy;
784 r->res_info = *resinfo;
787 /* Define a dialog control. This does not define a resource, but
788 merely allocates and fills in a structure. */
790 struct dialog_control *
791 define_control (const struct res_id iid, unsigned long id, unsigned long x,
792 unsigned long y, unsigned long width, unsigned long height,
793 unsigned long class, unsigned long style,
794 unsigned long exstyle)
796 struct dialog_control *n;
798 n = (struct dialog_control *) res_alloc (sizeof *n);
799 n->next = NULL;
800 n->id = id;
801 n->style = style;
802 n->exstyle = exstyle;
803 n->x = x;
804 n->y = y;
805 n->width = width;
806 n->height = height;
807 n->class.named = 0;
808 n->class.u.id = class;
809 n->text = iid;
810 n->data = NULL;
811 n->help = 0;
813 return n;
816 struct dialog_control *
817 define_icon_control (struct res_id iid, unsigned long id, unsigned long x,
818 unsigned long y, unsigned long style,
819 unsigned long exstyle, unsigned long help,
820 struct rcdata_item *data, struct dialog_ex *ex)
822 struct dialog_control *n;
823 struct res_id tid;
825 if (style == 0)
826 style = SS_ICON | WS_CHILD | WS_VISIBLE;
827 res_string_to_id (&tid, "");
828 n = define_control (tid, id, x, y, 0, 0, CTL_STATIC, style, exstyle);
829 n->text = iid;
830 if (help && !ex)
831 rcparse_warning (_("help ID requires DIALOGEX"));
832 if (data && !ex)
833 rcparse_warning (_("control data requires DIALOGEX"));
834 n->help = help;
835 n->data = data;
837 return n;
840 /* Define a font resource. */
842 void
843 define_font (struct res_id id, const struct res_res_info *resinfo,
844 const char *filename)
846 FILE *e;
847 char *real_filename;
848 struct stat s;
849 unsigned char *data;
850 struct res_resource *r;
851 long offset;
852 long fontdatalength;
853 unsigned char *fontdata;
854 struct fontdir *fd;
855 const char *device, *face;
856 struct fontdir **pp;
858 e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
860 if (stat (real_filename, &s) < 0)
861 fatal (_("stat failed on font file `%s': %s"), real_filename,
862 strerror (errno));
864 data = (unsigned char *) res_alloc (s.st_size);
866 get_data (e, data, s.st_size, real_filename);
868 fclose (e);
869 free (real_filename);
871 r = define_standard_resource (&resources, RT_FONT, id,
872 resinfo->language, 0);
874 r->type = RES_TYPE_FONT;
875 r->u.data.length = s.st_size;
876 r->u.data.data = data;
877 r->res_info = *resinfo;
879 /* For each font resource, we must add an entry in the FONTDIR
880 resource. The FONTDIR resource includes some strings in the font
881 file. To find them, we have to do some magic on the data we have
882 read. */
884 offset = ((((((data[47] << 8)
885 | data[46]) << 8)
886 | data[45]) << 8)
887 | data[44]);
888 if (offset > 0 && offset < s.st_size)
889 device = (char *) data + offset;
890 else
891 device = "";
893 offset = ((((((data[51] << 8)
894 | data[50]) << 8)
895 | data[49]) << 8)
896 | data[48]);
897 if (offset > 0 && offset < s.st_size)
898 face = (char *) data + offset;
899 else
900 face = "";
902 ++fonts;
904 fontdatalength = 58 + strlen (device) + strlen (face);
905 fontdata = (unsigned char *) res_alloc (fontdatalength);
906 memcpy (fontdata, data, 56);
907 strcpy ((char *) fontdata + 56, device);
908 strcpy ((char *) fontdata + 57 + strlen (device), face);
910 fd = (struct fontdir *) res_alloc (sizeof *fd);
911 fd->next = NULL;
912 fd->index = fonts;
913 fd->length = fontdatalength;
914 fd->data = fontdata;
916 for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next)
918 *pp = fd;
920 /* For the single fontdirs resource, we always use the resource
921 information of the last font. I don't know what else to do. */
922 fontdirs_resinfo = *resinfo;
925 /* Define the fontdirs resource. This is called after the entire rc
926 file has been parsed, if any font resources were seen. */
928 static void
929 define_fontdirs (void)
931 struct res_resource *r;
932 struct res_id id;
934 id.named = 0;
935 id.u.id = 1;
937 r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
939 r->type = RES_TYPE_FONTDIR;
940 r->u.fontdir = fontdirs;
941 r->res_info = fontdirs_resinfo;
944 /* Define an icon resource. An icon file may contain a set of
945 bitmaps, each representing the same icon at various different
946 resolutions. They each get written out with a different ID. The
947 real icon resource is then a group resource which can be used to
948 select one of the actual icon bitmaps. */
950 void
951 define_icon (struct res_id id, const struct res_res_info *resinfo,
952 const char *filename)
954 FILE *e;
955 char *real_filename;
956 int type, count, i;
957 struct icondir *icondirs;
958 int first_icon;
959 struct res_resource *r;
960 struct group_icon *first, **pp;
962 e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename);
964 /* The start of an icon file is a three word structure. The first
965 word is ignored. The second word is the type of data. The third
966 word is the number of entries. */
968 get_word (e, real_filename);
969 type = get_word (e, real_filename);
970 count = get_word (e, real_filename);
971 if (type != 1)
972 fatal (_("icon file `%s' does not contain icon data"), real_filename);
974 /* Read in the icon directory entries. */
976 icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
978 for (i = 0; i < count; i++)
980 icondirs[i].width = getc (e);
981 icondirs[i].height = getc (e);
982 icondirs[i].colorcount = getc (e);
983 getc (e);
984 icondirs[i].u.icon.planes = get_word (e, real_filename);
985 icondirs[i].u.icon.bits = get_word (e, real_filename);
986 icondirs[i].bytes = get_long (e, real_filename);
987 icondirs[i].offset = get_long (e, real_filename);
989 if (feof (e))
990 unexpected_eof (real_filename);
993 /* Define each icon as a unique resource. */
995 first_icon = icons;
997 for (i = 0; i < count; i++)
999 unsigned char *data;
1000 struct res_id name;
1002 if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
1003 fatal (_("%s: fseek to %lu failed: %s"), real_filename,
1004 icondirs[i].offset, strerror (errno));
1006 data = (unsigned char *) res_alloc (icondirs[i].bytes);
1008 get_data (e, data, icondirs[i].bytes, real_filename);
1010 ++icons;
1012 name.named = 0;
1013 name.u.id = icons;
1015 r = define_standard_resource (&resources, RT_ICON, name,
1016 resinfo->language, 0);
1017 r->type = RES_TYPE_ICON;
1018 r->u.data.length = icondirs[i].bytes;
1019 r->u.data.data = data;
1020 r->res_info = *resinfo;
1023 fclose (e);
1024 free (real_filename);
1026 /* Define an icon group resource. */
1028 first = NULL;
1029 pp = &first;
1030 for (i = 0; i < count; i++)
1032 struct group_icon *cg;
1034 /* For some reason, at least in some files the planes and bits
1035 are zero. We instead set them from the color. This is
1036 copied from rcl. */
1038 cg = (struct group_icon *) res_alloc (sizeof *cg);
1039 cg->next = NULL;
1040 cg->width = icondirs[i].width;
1041 cg->height = icondirs[i].height;
1042 cg->colors = icondirs[i].colorcount;
1044 if (icondirs[i].u.icon.planes)
1045 cg->planes = icondirs[i].u.icon.planes;
1046 else
1047 cg->planes = 1;
1049 if (icondirs[i].u.icon.bits)
1050 cg->bits = icondirs[i].u.icon.bits;
1051 else
1053 cg->bits = 0;
1055 while ((1L << cg->bits) < cg->colors)
1056 ++cg->bits;
1059 cg->bytes = icondirs[i].bytes;
1060 cg->index = first_icon + i + 1;
1062 *pp = cg;
1063 pp = &(*pp)->next;
1066 free (icondirs);
1068 r = define_standard_resource (&resources, RT_GROUP_ICON, id,
1069 resinfo->language, 0);
1070 r->type = RES_TYPE_GROUP_ICON;
1071 r->u.group_icon = first;
1072 r->res_info = *resinfo;
1075 /* Define a menu resource. */
1077 void
1078 define_menu (struct res_id id, const struct res_res_info *resinfo,
1079 struct menuitem *menuitems)
1081 struct menu *m;
1082 struct res_resource *r;
1084 m = (struct menu *) res_alloc (sizeof *m);
1085 m->items = menuitems;
1086 m->help = 0;
1088 r = define_standard_resource (&resources, RT_MENU, id, resinfo->language, 0);
1089 r->type = RES_TYPE_MENU;
1090 r->u.menu = m;
1091 r->res_info = *resinfo;
1094 /* Define a menu item. This does not define a resource, but merely
1095 allocates and fills in a structure. */
1097 struct menuitem *
1098 define_menuitem (const char *text, int menuid, unsigned long type,
1099 unsigned long state, unsigned long help,
1100 struct menuitem *menuitems)
1102 struct menuitem *mi;
1104 mi = (struct menuitem *) res_alloc (sizeof *mi);
1105 mi->next = NULL;
1106 mi->type = type;
1107 mi->state = state;
1108 mi->id = menuid;
1109 if (text == NULL)
1110 mi->text = NULL;
1111 else
1112 unicode_from_ascii ((int *) NULL, &mi->text, text);
1113 mi->help = help;
1114 mi->popup = menuitems;
1115 return mi;
1118 /* Define a messagetable resource. */
1120 void
1121 define_messagetable (struct res_id id, const struct res_res_info *resinfo,
1122 const char *filename)
1124 FILE *e;
1125 char *real_filename;
1126 struct stat s;
1127 unsigned char *data;
1128 struct res_resource *r;
1130 e = open_file_search (filename, FOPEN_RB, "messagetable file",
1131 &real_filename);
1133 if (stat (real_filename, &s) < 0)
1134 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
1135 strerror (errno));
1137 data = (unsigned char *) res_alloc (s.st_size);
1139 get_data (e, data, s.st_size, real_filename);
1141 fclose (e);
1142 free (real_filename);
1144 r = define_standard_resource (&resources, RT_MESSAGETABLE, id,
1145 resinfo->language, 0);
1147 r->type = RES_TYPE_MESSAGETABLE;
1148 r->u.data.length = s.st_size;
1149 r->u.data.data = data;
1150 r->res_info = *resinfo;
1153 /* Define an rcdata resource. */
1155 void
1156 define_rcdata (struct res_id id, const struct res_res_info *resinfo,
1157 struct rcdata_item *data)
1159 struct res_resource *r;
1161 r = define_standard_resource (&resources, RT_RCDATA, id,
1162 resinfo->language, 0);
1163 r->type = RES_TYPE_RCDATA;
1164 r->u.rcdata = data;
1165 r->res_info = *resinfo;
1168 /* Create an rcdata item holding a string. */
1170 struct rcdata_item *
1171 define_rcdata_string (const char *string, unsigned long len)
1173 struct rcdata_item *ri;
1174 char *s;
1176 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
1177 ri->next = NULL;
1178 ri->type = RCDATA_STRING;
1179 ri->u.string.length = len;
1180 s = (char *) res_alloc (len);
1181 memcpy (s, string, len);
1182 ri->u.string.s = s;
1184 return ri;
1187 /* Create an rcdata item holding a number. */
1189 struct rcdata_item *
1190 define_rcdata_number (unsigned long val, int dword)
1192 struct rcdata_item *ri;
1194 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
1195 ri->next = NULL;
1196 ri->type = dword ? RCDATA_DWORD : RCDATA_WORD;
1197 ri->u.word = val;
1199 return ri;
1202 /* Define a stringtable resource. This is called for each string
1203 which appears in a STRINGTABLE statement. */
1205 void
1206 define_stringtable (const struct res_res_info *resinfo,
1207 unsigned long stringid, const char *string)
1209 struct res_id id;
1210 struct res_resource *r;
1212 id.named = 0;
1213 id.u.id = (stringid >> 4) + 1;
1214 r = define_standard_resource (&resources, RT_STRING, id,
1215 resinfo->language, 1);
1217 if (r->type == RES_TYPE_UNINITIALIZED)
1219 int i;
1221 r->type = RES_TYPE_STRINGTABLE;
1222 r->u.stringtable = ((struct stringtable *)
1223 res_alloc (sizeof (struct stringtable)));
1224 for (i = 0; i < 16; i++)
1226 r->u.stringtable->strings[i].length = 0;
1227 r->u.stringtable->strings[i].string = NULL;
1230 r->res_info = *resinfo;
1233 unicode_from_ascii (&r->u.stringtable->strings[stringid & 0xf].length,
1234 &r->u.stringtable->strings[stringid & 0xf].string,
1235 string);
1238 /* Define a user data resource where the data is in the rc file. */
1240 void
1241 define_user_data (struct res_id id, struct res_id type,
1242 const struct res_res_info *resinfo,
1243 struct rcdata_item *data)
1245 struct res_id ids[3];
1246 struct res_resource *r;
1248 ids[0] = type;
1249 ids[1] = id;
1250 ids[2].named = 0;
1251 ids[2].u.id = resinfo->language;
1253 r = define_resource (& resources, 3, ids, 0);
1254 r->type = RES_TYPE_USERDATA;
1255 r->u.userdata = data;
1256 r->res_info = *resinfo;
1259 void
1260 define_rcdata_file (struct res_id id, const struct res_res_info *resinfo,
1261 const char *filename)
1263 struct rcdata_item *ri;
1264 FILE *e;
1265 char *real_filename;
1266 struct stat s;
1267 unsigned char *data;
1269 e = open_file_search (filename, FOPEN_RB, "file", &real_filename);
1272 if (stat (real_filename, &s) < 0)
1273 fatal (_("stat failed on file `%s': %s"), real_filename,
1274 strerror (errno));
1276 data = (unsigned char *) res_alloc (s.st_size);
1278 get_data (e, data, s.st_size, real_filename);
1280 fclose (e);
1281 free (real_filename);
1283 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
1284 ri->next = NULL;
1285 ri->type = RCDATA_BUFFER;
1286 ri->u.buffer.length = s.st_size;
1287 ri->u.buffer.data = data;
1289 define_rcdata (id, resinfo, ri);
1292 /* Define a user data resource where the data is in a file. */
1294 void
1295 define_user_file (struct res_id id, struct res_id type,
1296 const struct res_res_info *resinfo, const char *filename)
1298 FILE *e;
1299 char *real_filename;
1300 struct stat s;
1301 unsigned char *data;
1302 struct res_id ids[3];
1303 struct res_resource *r;
1305 e = open_file_search (filename, FOPEN_RB, "file", &real_filename);
1307 if (stat (real_filename, &s) < 0)
1308 fatal (_("stat failed on file `%s': %s"), real_filename,
1309 strerror (errno));
1311 data = (unsigned char *) res_alloc (s.st_size);
1313 get_data (e, data, s.st_size, real_filename);
1315 fclose (e);
1316 free (real_filename);
1318 ids[0] = type;
1319 ids[1] = id;
1320 ids[2].named = 0;
1321 ids[2].u.id = resinfo->language;
1323 r = define_resource (&resources, 3, ids, 0);
1324 r->type = RES_TYPE_USERDATA;
1325 r->u.userdata = ((struct rcdata_item *)
1326 res_alloc (sizeof (struct rcdata_item)));
1327 r->u.userdata->next = NULL;
1328 r->u.userdata->type = RCDATA_BUFFER;
1329 r->u.userdata->u.buffer.length = s.st_size;
1330 r->u.userdata->u.buffer.data = data;
1331 r->res_info = *resinfo;
1334 /* Define a versioninfo resource. */
1336 void
1337 define_versioninfo (struct res_id id, int language,
1338 struct fixed_versioninfo *fixedverinfo,
1339 struct ver_info *verinfo)
1341 struct res_resource *r;
1343 r = define_standard_resource (&resources, RT_VERSION, id, language, 0);
1344 r->type = RES_TYPE_VERSIONINFO;
1345 r->u.versioninfo = ((struct versioninfo *)
1346 res_alloc (sizeof (struct versioninfo)));
1347 r->u.versioninfo->fixed = fixedverinfo;
1348 r->u.versioninfo->var = verinfo;
1349 r->res_info.language = language;
1352 /* Add string version info to a list of version information. */
1354 struct ver_info *
1355 append_ver_stringfileinfo (struct ver_info *verinfo, const char *language,
1356 struct ver_stringinfo *strings)
1358 struct ver_info *vi, **pp;
1360 vi = (struct ver_info *) res_alloc (sizeof *vi);
1361 vi->next = NULL;
1362 vi->type = VERINFO_STRING;
1363 unicode_from_ascii ((int *) NULL, &vi->u.string.language, language);
1364 vi->u.string.strings = strings;
1366 for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1368 *pp = vi;
1370 return verinfo;
1373 /* Add variable version info to a list of version information. */
1375 struct ver_info *
1376 append_ver_varfileinfo (struct ver_info *verinfo, const char *key,
1377 struct ver_varinfo *var)
1379 struct ver_info *vi, **pp;
1381 vi = (struct ver_info *) res_alloc (sizeof *vi);
1382 vi->next = NULL;
1383 vi->type = VERINFO_VAR;
1384 unicode_from_ascii ((int *) NULL, &vi->u.var.key, key);
1385 vi->u.var.var = var;
1387 for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1389 *pp = vi;
1391 return verinfo;
1394 /* Append version string information to a list. */
1396 struct ver_stringinfo *
1397 append_verval (struct ver_stringinfo *strings, const char *key,
1398 const char *value)
1400 struct ver_stringinfo *vs, **pp;
1402 vs = (struct ver_stringinfo *) res_alloc (sizeof *vs);
1403 vs->next = NULL;
1404 unicode_from_ascii ((int *) NULL, &vs->key, key);
1405 unicode_from_ascii ((int *) NULL, &vs->value, value);
1407 for (pp = &strings; *pp != NULL; pp = &(*pp)->next)
1409 *pp = vs;
1411 return strings;
1414 /* Append version variable information to a list. */
1416 struct ver_varinfo *
1417 append_vertrans (struct ver_varinfo *var, unsigned long language,
1418 unsigned long charset)
1420 struct ver_varinfo *vv, **pp;
1422 vv = (struct ver_varinfo *) res_alloc (sizeof *vv);
1423 vv->next = NULL;
1424 vv->language = language;
1425 vv->charset = charset;
1427 for (pp = &var; *pp != NULL; pp = &(*pp)->next)
1429 *pp = vv;
1431 return var;
1434 /* Local functions used to write out an rc file. */
1436 static void indent (FILE *, int);
1437 static void write_rc_directory
1438 (FILE *, const struct res_directory *, const struct res_id *,
1439 const struct res_id *, int *, int);
1440 static void write_rc_subdir
1441 (FILE *, const struct res_entry *, const struct res_id *,
1442 const struct res_id *, int *, int);
1443 static void write_rc_resource
1444 (FILE *, const struct res_id *, const struct res_id *,
1445 const struct res_resource *, int *);
1446 static void write_rc_accelerators (FILE *, const struct accelerator *);
1447 static void write_rc_cursor (FILE *, const struct cursor *);
1448 static void write_rc_group_cursor (FILE *, const struct group_cursor *);
1449 static void write_rc_dialog (FILE *, const struct dialog *);
1450 static void write_rc_dialog_control (FILE *, const struct dialog_control *);
1451 static void write_rc_fontdir (FILE *, const struct fontdir *);
1452 static void write_rc_group_icon (FILE *, const struct group_icon *);
1453 static void write_rc_menu (FILE *, const struct menu *, int);
1454 static void write_rc_menuitems (FILE *, const struct menuitem *, int, int);
1455 static void write_rc_rcdata (FILE *, const struct rcdata_item *, int);
1456 static void write_rc_stringtable
1457 (FILE *, const struct res_id *, const struct stringtable *);
1458 static void write_rc_versioninfo (FILE *, const struct versioninfo *);
1459 static void write_rc_filedata (FILE *, unsigned long, const unsigned char *);
1461 /* Indent a given number of spaces. */
1463 static void
1464 indent (FILE *e, int c)
1466 int i;
1468 for (i = 0; i < c; i++)
1469 putc (' ', e);
1472 /* Dump the resources we have read in the format of an rc file.
1474 Actually, we don't use the format of an rc file, because it's way
1475 too much of a pain--for example, we'd have to write icon resources
1476 into a file and refer to that file. We just generate a readable
1477 format that kind of looks like an rc file, and is useful for
1478 understanding the contents of a resource file. Someday we may want
1479 to generate an rc file which the rc compiler can read; if that day
1480 comes, this code will have to be fixed up. */
1482 void
1483 write_rc_file (const char *filename, const struct res_directory *resources)
1485 FILE *e;
1486 int language;
1488 if (filename == NULL)
1489 e = stdout;
1490 else
1492 e = fopen (filename, FOPEN_WT);
1493 if (e == NULL)
1494 fatal (_("can't open `%s' for output: %s"), filename, strerror (errno));
1497 language = -1;
1498 write_rc_directory (e, resources, (const struct res_id *) NULL,
1499 (const struct res_id *) NULL, &language, 1);
1502 /* Write out a directory. E is the file to write to. RD is the
1503 directory. TYPE is a pointer to the level 1 ID which serves as the
1504 resource type. NAME is a pointer to the level 2 ID which serves as
1505 an individual resource name. LANGUAGE is a pointer to the current
1506 language. LEVEL is the level in the tree. */
1508 static void
1509 write_rc_directory (FILE *e, const struct res_directory *rd,
1510 const struct res_id *type, const struct res_id *name,
1511 int *language, int level)
1513 const struct res_entry *re;
1515 /* Print out some COFF information that rc files can't represent. */
1517 if (rd->time != 0)
1518 fprintf (e, "// Time stamp: %lu\n", rd->time);
1519 if (rd->characteristics != 0)
1520 fprintf (e, "// Characteristics: %lu\n", rd->characteristics);
1521 if (rd->major != 0 || rd->minor != 0)
1522 fprintf (e, "// Version: %d %d\n", rd->major, rd->minor);
1524 for (re = rd->entries; re != NULL; re = re->next)
1526 switch (level)
1528 case 1:
1529 /* If we're at level 1, the key of this resource is the
1530 type. This normally duplicates the information we have
1531 stored with the resource itself, but we need to remember
1532 the type if this is a user define resource type. */
1533 type = &re->id;
1534 break;
1536 case 2:
1537 /* If we're at level 2, the key of this resource is the name
1538 we are going to use in the rc printout. */
1539 name = &re->id;
1540 break;
1542 case 3:
1543 /* If we're at level 3, then this key represents a language.
1544 Use it to update the current language. */
1545 if (! re->id.named
1546 && re->id.u.id != (unsigned long) (unsigned int) *language
1547 && (re->id.u.id & 0xffff) == re->id.u.id)
1549 fprintf (e, "LANGUAGE %lu, %lu\n",
1550 re->id.u.id & ((1 << SUBLANG_SHIFT) - 1),
1551 (re->id.u.id >> SUBLANG_SHIFT) & 0xff);
1552 *language = re->id.u.id;
1554 break;
1556 default:
1557 break;
1560 if (re->subdir)
1561 write_rc_subdir (e, re, type, name, language, level);
1562 else
1564 if (level == 3)
1566 /* This is the normal case: the three levels are
1567 TYPE/NAME/LANGUAGE. NAME will have been set at level
1568 2, and represents the name to use. We probably just
1569 set LANGUAGE, and it will probably match what the
1570 resource itself records if anything. */
1571 write_rc_resource (e, type, name, re->u.res, language);
1573 else
1575 fprintf (e, "// Resource at unexpected level %d\n", level);
1576 write_rc_resource (e, type, (struct res_id *) NULL, re->u.res,
1577 language);
1583 /* Write out a subdirectory entry. E is the file to write to. RE is
1584 the subdirectory entry. TYPE and NAME are pointers to higher level
1585 IDs, or NULL. LANGUAGE is a pointer to the current language.
1586 LEVEL is the level in the tree. */
1588 static void
1589 write_rc_subdir (FILE *e, const struct res_entry *re,
1590 const struct res_id *type, const struct res_id *name,
1591 int *language, int level)
1593 fprintf (e, "\n");
1594 switch (level)
1596 case 1:
1597 fprintf (e, "// Type: ");
1598 if (re->id.named)
1599 res_id_print (e, re->id, 1);
1600 else
1602 const char *s;
1604 switch (re->id.u.id)
1606 case RT_CURSOR: s = "cursor"; break;
1607 case RT_BITMAP: s = "bitmap"; break;
1608 case RT_ICON: s = "icon"; break;
1609 case RT_MENU: s = "menu"; break;
1610 case RT_DIALOG: s = "dialog"; break;
1611 case RT_STRING: s = "stringtable"; break;
1612 case RT_FONTDIR: s = "fontdir"; break;
1613 case RT_FONT: s = "font"; break;
1614 case RT_ACCELERATOR: s = "accelerators"; break;
1615 case RT_RCDATA: s = "rcdata"; break;
1616 case RT_MESSAGETABLE: s = "messagetable"; break;
1617 case RT_GROUP_CURSOR: s = "group cursor"; break;
1618 case RT_GROUP_ICON: s = "group icon"; break;
1619 case RT_VERSION: s = "version"; break;
1620 case RT_DLGINCLUDE: s = "dlginclude"; break;
1621 case RT_PLUGPLAY: s = "plugplay"; break;
1622 case RT_VXD: s = "vxd"; break;
1623 case RT_ANICURSOR: s = "anicursor"; break;
1624 case RT_ANIICON: s = "aniicon"; break;
1625 default: s = NULL; break;
1628 if (s != NULL)
1629 fprintf (e, "%s", s);
1630 else
1631 res_id_print (e, re->id, 1);
1633 fprintf (e, "\n");
1634 break;
1636 case 2:
1637 fprintf (e, "// Name: ");
1638 res_id_print (e, re->id, 1);
1639 fprintf (e, "\n");
1640 break;
1642 case 3:
1643 fprintf (e, "// Language: ");
1644 res_id_print (e, re->id, 1);
1645 fprintf (e, "\n");
1646 break;
1648 default:
1649 fprintf (e, "// Level %d: ", level);
1650 res_id_print (e, re->id, 1);
1651 fprintf (e, "\n");
1654 write_rc_directory (e, re->u.dir, type, name, language, level + 1);
1657 /* Write out a single resource. E is the file to write to. TYPE is a
1658 pointer to the type of the resource. NAME is a pointer to the name
1659 of the resource; it will be NULL if there is a level mismatch. RES
1660 is the resource data. LANGUAGE is a pointer to the current
1661 language. */
1663 static void
1664 write_rc_resource (FILE *e, const struct res_id *type,
1665 const struct res_id *name, const struct res_resource *res,
1666 int *language)
1668 const char *s;
1669 int rt;
1670 int menuex = 0;
1672 fprintf (e, "\n");
1674 switch (res->type)
1676 default:
1677 abort ();
1679 case RES_TYPE_ACCELERATOR:
1680 s = "ACCELERATOR";
1681 rt = RT_ACCELERATOR;
1682 break;
1684 case RES_TYPE_BITMAP:
1685 s = "BITMAP";
1686 rt = RT_BITMAP;
1687 break;
1689 case RES_TYPE_CURSOR:
1690 s = "CURSOR";
1691 rt = RT_CURSOR;
1692 break;
1694 case RES_TYPE_GROUP_CURSOR:
1695 s = "GROUP_CURSOR";
1696 rt = RT_GROUP_CURSOR;
1697 break;
1699 case RES_TYPE_DIALOG:
1700 if (extended_dialog (res->u.dialog))
1701 s = "DIALOGEX";
1702 else
1703 s = "DIALOG";
1704 rt = RT_DIALOG;
1705 break;
1707 case RES_TYPE_FONT:
1708 s = "FONT";
1709 rt = RT_FONT;
1710 break;
1712 case RES_TYPE_FONTDIR:
1713 s = "FONTDIR";
1714 rt = RT_FONTDIR;
1715 break;
1717 case RES_TYPE_ICON:
1718 s = "ICON";
1719 rt = RT_ICON;
1720 break;
1722 case RES_TYPE_GROUP_ICON:
1723 s = "GROUP_ICON";
1724 rt = RT_GROUP_ICON;
1725 break;
1727 case RES_TYPE_MENU:
1728 if (extended_menu (res->u.menu))
1730 s = "MENUEX";
1731 menuex = 1;
1733 else
1735 s = "MENU";
1736 menuex = 0;
1738 rt = RT_MENU;
1739 break;
1741 case RES_TYPE_MESSAGETABLE:
1742 s = "MESSAGETABLE";
1743 rt = RT_MESSAGETABLE;
1744 break;
1746 case RES_TYPE_RCDATA:
1747 s = "RCDATA";
1748 rt = RT_RCDATA;
1749 break;
1751 case RES_TYPE_STRINGTABLE:
1752 s = "STRINGTABLE";
1753 rt = RT_STRING;
1754 break;
1756 case RES_TYPE_USERDATA:
1757 s = NULL;
1758 rt = 0;
1759 break;
1761 case RES_TYPE_VERSIONINFO:
1762 s = "VERSIONINFO";
1763 rt = RT_VERSION;
1764 break;
1767 if (rt != 0
1768 && type != NULL
1769 && (type->named || type->u.id != (unsigned long) rt))
1771 fprintf (e, "// Unexpected resource type mismatch: ");
1772 res_id_print (e, *type, 1);
1773 fprintf (e, " != %d", rt);
1776 if (res->coff_info.codepage != 0)
1777 fprintf (e, "// Code page: %lu\n", res->coff_info.codepage);
1778 if (res->coff_info.reserved != 0)
1779 fprintf (e, "// COFF reserved value: %lu\n", res->coff_info.reserved);
1781 if (name != NULL)
1782 res_id_print (e, *name, 0);
1783 else
1784 fprintf (e, "??Unknown-Name??");
1786 fprintf (e, " ");
1787 if (s != NULL)
1788 fprintf (e, "%s", s);
1789 else if (type != NULL)
1790 res_id_print (e, *type, 0);
1791 else
1792 fprintf (e, "??Unknown-Type??");
1794 if (res->res_info.memflags != 0)
1796 if ((res->res_info.memflags & MEMFLAG_MOVEABLE) != 0)
1797 fprintf (e, " MOVEABLE");
1798 if ((res->res_info.memflags & MEMFLAG_PURE) != 0)
1799 fprintf (e, " PURE");
1800 if ((res->res_info.memflags & MEMFLAG_PRELOAD) != 0)
1801 fprintf (e, " PRELOAD");
1802 if ((res->res_info.memflags & MEMFLAG_DISCARDABLE) != 0)
1803 fprintf (e, " DISCARDABLE");
1806 if (res->type == RES_TYPE_DIALOG)
1808 fprintf (e, " %d, %d, %d, %d", res->u.dialog->x, res->u.dialog->y,
1809 res->u.dialog->width, res->u.dialog->height);
1810 if (res->u.dialog->ex != NULL
1811 && res->u.dialog->ex->help != 0)
1812 fprintf (e, ", %lu", res->u.dialog->ex->help);
1815 fprintf (e, "\n");
1817 if ((res->res_info.language != 0 && res->res_info.language != *language)
1818 || res->res_info.characteristics != 0
1819 || res->res_info.version != 0)
1821 int modifiers;
1823 switch (res->type)
1825 case RES_TYPE_ACCELERATOR:
1826 case RES_TYPE_DIALOG:
1827 case RES_TYPE_MENU:
1828 case RES_TYPE_RCDATA:
1829 case RES_TYPE_STRINGTABLE:
1830 modifiers = 1;
1831 break;
1833 default:
1834 modifiers = 0;
1835 break;
1838 if (res->res_info.language != 0 && res->res_info.language != *language)
1839 fprintf (e, "%sLANGUAGE %d, %d\n",
1840 modifiers ? "// " : "",
1841 res->res_info.language & ((1<<SUBLANG_SHIFT)-1),
1842 (res->res_info.language >> SUBLANG_SHIFT) & 0xff);
1843 if (res->res_info.characteristics != 0)
1844 fprintf (e, "%sCHARACTERISTICS %lu\n",
1845 modifiers ? "// " : "",
1846 res->res_info.characteristics);
1847 if (res->res_info.version != 0)
1848 fprintf (e, "%sVERSION %lu\n",
1849 modifiers ? "// " : "",
1850 res->res_info.version);
1853 switch (res->type)
1855 default:
1856 abort ();
1858 case RES_TYPE_ACCELERATOR:
1859 write_rc_accelerators (e, res->u.acc);
1860 break;
1862 case RES_TYPE_CURSOR:
1863 write_rc_cursor (e, res->u.cursor);
1864 break;
1866 case RES_TYPE_GROUP_CURSOR:
1867 write_rc_group_cursor (e, res->u.group_cursor);
1868 break;
1870 case RES_TYPE_DIALOG:
1871 write_rc_dialog (e, res->u.dialog);
1872 break;
1874 case RES_TYPE_FONTDIR:
1875 write_rc_fontdir (e, res->u.fontdir);
1876 break;
1878 case RES_TYPE_GROUP_ICON:
1879 write_rc_group_icon (e, res->u.group_icon);
1880 break;
1882 case RES_TYPE_MENU:
1883 write_rc_menu (e, res->u.menu, menuex);
1884 break;
1886 case RES_TYPE_RCDATA:
1887 write_rc_rcdata (e, res->u.rcdata, 0);
1888 break;
1890 case RES_TYPE_STRINGTABLE:
1891 write_rc_stringtable (e, name, res->u.stringtable);
1892 break;
1894 case RES_TYPE_USERDATA:
1895 write_rc_rcdata (e, res->u.userdata, 0);
1896 break;
1898 case RES_TYPE_VERSIONINFO:
1899 write_rc_versioninfo (e, res->u.versioninfo);
1900 break;
1902 case RES_TYPE_BITMAP:
1903 case RES_TYPE_FONT:
1904 case RES_TYPE_ICON:
1905 case RES_TYPE_MESSAGETABLE:
1906 write_rc_filedata (e, res->u.data.length, res->u.data.data);
1907 break;
1911 /* Write out accelerator information. */
1913 static void
1914 write_rc_accelerators (FILE *e, const struct accelerator *accelerators)
1916 const struct accelerator *acc;
1918 fprintf (e, "BEGIN\n");
1919 for (acc = accelerators; acc != NULL; acc = acc->next)
1921 int printable;
1923 fprintf (e, " ");
1925 if ((acc->key & 0x7f) == acc->key
1926 && ISPRINT (acc->key)
1927 && (acc->flags & ACC_VIRTKEY) == 0)
1929 fprintf (e, "\"%c\"", acc->key);
1930 printable = 1;
1932 else
1934 fprintf (e, "%d", acc->key);
1935 printable = 0;
1938 fprintf (e, ", %d", acc->id);
1940 if (! printable)
1942 if ((acc->flags & ACC_VIRTKEY) != 0)
1943 fprintf (e, ", VIRTKEY");
1944 else
1945 fprintf (e, ", ASCII");
1948 if ((acc->flags & ACC_SHIFT) != 0)
1949 fprintf (e, ", SHIFT");
1950 if ((acc->flags & ACC_CONTROL) != 0)
1951 fprintf (e, ", CONTROL");
1952 if ((acc->flags & ACC_ALT) != 0)
1953 fprintf (e, ", ALT");
1955 fprintf (e, "\n");
1958 fprintf (e, "END\n");
1961 /* Write out cursor information. This would normally be in a separate
1962 file, which the rc file would include. */
1964 static void
1965 write_rc_cursor (FILE *e, const struct cursor *cursor)
1967 fprintf (e, "// Hotspot: x: %d; y: %d\n", cursor->xhotspot,
1968 cursor->yhotspot);
1969 write_rc_filedata (e, cursor->length, cursor->data);
1972 /* Write out group cursor data. This would normally be built from the
1973 cursor data. */
1975 static void
1976 write_rc_group_cursor (FILE *e, const struct group_cursor *group_cursor)
1978 const struct group_cursor *gc;
1980 for (gc = group_cursor; gc != NULL; gc = gc->next)
1982 fprintf (e, "// width: %d; height %d; planes %d; bits %d\n",
1983 gc->width, gc->height, gc->planes, gc->bits);
1984 fprintf (e, "// data bytes: %lu; index: %d\n",
1985 gc->bytes, gc->index);
1989 /* Write dialog data. */
1991 static void
1992 write_rc_dialog (FILE *e, const struct dialog *dialog)
1994 const struct dialog_control *control;
1996 fprintf (e, "STYLE 0x%lx\n", dialog->style);
1998 if (dialog->exstyle != 0)
1999 fprintf (e, "EXSTYLE 0x%lx\n", dialog->exstyle);
2001 if ((dialog->class.named && dialog->class.u.n.length > 0)
2002 || dialog->class.u.id != 0)
2004 fprintf (e, "CLASS ");
2005 res_id_print (e, dialog->class, 1);
2006 fprintf (e, "\n");
2009 if (dialog->caption != NULL)
2011 fprintf (e, "CAPTION \"");
2012 unicode_print (e, dialog->caption, -1);
2013 fprintf (e, "\"\n");
2016 if ((dialog->menu.named && dialog->menu.u.n.length > 0)
2017 || dialog->menu.u.id != 0)
2019 fprintf (e, "MENU ");
2020 res_id_print (e, dialog->menu, 0);
2021 fprintf (e, "\n");
2024 if (dialog->font != NULL)
2026 fprintf (e, "FONT %d, \"", dialog->pointsize);
2027 unicode_print (e, dialog->font, -1);
2028 fprintf (e, "\"");
2029 if (dialog->ex != NULL
2030 && (dialog->ex->weight != 0
2031 || dialog->ex->italic != 0
2032 || dialog->ex->charset != 1))
2033 fprintf (e, ", %d, %d, %d",
2034 dialog->ex->weight, dialog->ex->italic, dialog->ex->charset);
2035 fprintf (e, "\n");
2038 fprintf (e, "BEGIN\n");
2040 for (control = dialog->controls; control != NULL; control = control->next)
2041 write_rc_dialog_control (e, control);
2043 fprintf (e, "END\n");
2046 /* For each predefined control keyword, this table provides the class
2047 and the style. */
2049 struct control_info
2051 const char *name;
2052 unsigned short class;
2053 unsigned long style;
2056 static const struct control_info control_info[] =
2058 { "AUTO3STATE", CTL_BUTTON, BS_AUTO3STATE },
2059 { "AUTOCHECKBOX", CTL_BUTTON, BS_AUTOCHECKBOX },
2060 { "AUTORADIOBUTTON", CTL_BUTTON, BS_AUTORADIOBUTTON },
2061 { "CHECKBOX", CTL_BUTTON, BS_CHECKBOX },
2062 { "COMBOBOX", CTL_COMBOBOX, (unsigned long) -1 },
2063 { "CTEXT", CTL_STATIC, SS_CENTER },
2064 { "DEFPUSHBUTTON", CTL_BUTTON, BS_DEFPUSHBUTTON },
2065 { "EDITTEXT", CTL_EDIT, (unsigned long) -1 },
2066 { "GROUPBOX", CTL_BUTTON, BS_GROUPBOX },
2067 { "ICON", CTL_STATIC, SS_ICON },
2068 { "LISTBOX", CTL_LISTBOX, (unsigned long) -1 },
2069 { "LTEXT", CTL_STATIC, SS_LEFT },
2070 { "PUSHBOX", CTL_BUTTON, BS_PUSHBOX },
2071 { "PUSHBUTTON", CTL_BUTTON, BS_PUSHBUTTON },
2072 { "RADIOBUTTON", CTL_BUTTON, BS_RADIOBUTTON },
2073 { "RTEXT", CTL_STATIC, SS_RIGHT },
2074 { "SCROLLBAR", CTL_SCROLLBAR, (unsigned long) -1 },
2075 { "STATE3", CTL_BUTTON, BS_3STATE },
2076 /* It's important that USERBUTTON come after all the other button
2077 types, so that it won't be matched too early. */
2078 { "USERBUTTON", CTL_BUTTON, (unsigned long) -1 },
2079 { NULL, 0, 0 }
2082 /* Write a dialog control. */
2084 static void
2085 write_rc_dialog_control (FILE *e, const struct dialog_control *control)
2087 const struct control_info *ci;
2089 fprintf (e, " ");
2091 if (control->class.named)
2092 ci = NULL;
2093 else
2095 for (ci = control_info; ci->name != NULL; ++ci)
2096 if (ci->class == control->class.u.id
2097 && (ci->style == (unsigned long) -1
2098 || ci->style == (control->style & 0xff)))
2099 break;
2101 if (ci == NULL)
2102 fprintf (e, "CONTROL");
2103 else if (ci->name != NULL)
2104 fprintf (e, "%s", ci->name);
2105 else
2106 fprintf (e, "CONTROL");
2108 if (control->text.named || control->text.u.id != 0)
2110 fprintf (e, " ");
2111 res_id_print (e, control->text, 1);
2112 fprintf (e, ",");
2115 fprintf (e, " %d, ", control->id);
2117 if (ci == NULL)
2119 if (control->class.named)
2120 fprintf (e, "\"");
2121 res_id_print (e, control->class, 0);
2122 if (control->class.named)
2123 fprintf (e, "\"");
2124 fprintf (e, ", 0x%lx, ", control->style);
2127 fprintf (e, "%d, %d", control->x, control->y);
2129 if (control->style != SS_ICON
2130 || control->exstyle != 0
2131 || control->width != 0
2132 || control->height != 0
2133 || control->help != 0)
2135 fprintf (e, ", %d, %d", control->width, control->height);
2137 /* FIXME: We don't need to print the style if it is the default.
2138 More importantly, in certain cases we actually need to turn
2139 off parts of the forced style, by using NOT. */
2140 fprintf (e, ", 0x%lx", control->style);
2142 if (control->exstyle != 0 || control->help != 0)
2143 fprintf (e, ", 0x%lx, %lu", control->exstyle, control->help);
2146 fprintf (e, "\n");
2148 if (control->data != NULL)
2149 write_rc_rcdata (e, control->data, 2);
2152 /* Write out font directory data. This would normally be built from
2153 the font data. */
2155 static void
2156 write_rc_fontdir (FILE *e, const struct fontdir *fontdir)
2158 const struct fontdir *fc;
2160 for (fc = fontdir; fc != NULL; fc = fc->next)
2162 fprintf (e, "// Font index: %d\n", fc->index);
2163 write_rc_filedata (e, fc->length, fc->data);
2167 /* Write out group icon data. This would normally be built from the
2168 icon data. */
2170 static void
2171 write_rc_group_icon (FILE *e, const struct group_icon *group_icon)
2173 const struct group_icon *gi;
2175 for (gi = group_icon; gi != NULL; gi = gi->next)
2177 fprintf (e, "// width: %d; height %d; colors: %d; planes %d; bits %d\n",
2178 gi->width, gi->height, gi->colors, gi->planes, gi->bits);
2179 fprintf (e, "// data bytes: %lu; index: %d\n",
2180 gi->bytes, gi->index);
2184 /* Write out a menu resource. */
2186 static void
2187 write_rc_menu (FILE *e, const struct menu *menu, int menuex)
2189 if (menu->help != 0)
2190 fprintf (e, "// Help ID: %lu\n", menu->help);
2191 write_rc_menuitems (e, menu->items, menuex, 0);
2194 /* Write out menuitems. */
2196 static void
2197 write_rc_menuitems (FILE *e, const struct menuitem *menuitems, int menuex,
2198 int ind)
2200 const struct menuitem *mi;
2202 indent (e, ind);
2203 fprintf (e, "BEGIN\n");
2205 for (mi = menuitems; mi != NULL; mi = mi->next)
2207 indent (e, ind + 2);
2209 if (mi->popup == NULL)
2210 fprintf (e, "MENUITEM");
2211 else
2212 fprintf (e, "POPUP");
2214 if (! menuex
2215 && mi->popup == NULL
2216 && mi->text == NULL
2217 && mi->type == 0
2218 && mi->id == 0)
2220 fprintf (e, " SEPARATOR\n");
2221 continue;
2224 if (mi->text == NULL)
2225 fprintf (e, " \"\"");
2226 else
2228 fprintf (e, " \"");
2229 unicode_print (e, mi->text, -1);
2230 fprintf (e, "\"");
2233 if (! menuex)
2235 if (mi->popup == NULL)
2236 fprintf (e, ", %d", mi->id);
2238 if ((mi->type & MENUITEM_CHECKED) != 0)
2239 fprintf (e, ", CHECKED");
2240 if ((mi->type & MENUITEM_GRAYED) != 0)
2241 fprintf (e, ", GRAYED");
2242 if ((mi->type & MENUITEM_HELP) != 0)
2243 fprintf (e, ", HELP");
2244 if ((mi->type & MENUITEM_INACTIVE) != 0)
2245 fprintf (e, ", INACTIVE");
2246 if ((mi->type & MENUITEM_MENUBARBREAK) != 0)
2247 fprintf (e, ", MENUBARBREAK");
2248 if ((mi->type & MENUITEM_MENUBREAK) != 0)
2249 fprintf (e, ", MENUBREAK");
2251 else
2253 if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0)
2255 fprintf (e, ", %d", mi->id);
2256 if (mi->type != 0 || mi->state != 0 || mi->help != 0)
2258 fprintf (e, ", %lu", mi->type);
2259 if (mi->state != 0 || mi->help != 0)
2261 fprintf (e, ", %lu", mi->state);
2262 if (mi->help != 0)
2263 fprintf (e, ", %lu", mi->help);
2269 fprintf (e, "\n");
2271 if (mi->popup != NULL)
2272 write_rc_menuitems (e, mi->popup, menuex, ind + 2);
2275 indent (e, ind);
2276 fprintf (e, "END\n");
2279 /* Write out an rcdata resource. This is also used for other types of
2280 resources that need to print arbitrary data. */
2282 static void
2283 write_rc_rcdata (FILE *e, const struct rcdata_item *rcdata, int ind)
2285 const struct rcdata_item *ri;
2287 indent (e, ind);
2288 fprintf (e, "BEGIN\n");
2290 for (ri = rcdata; ri != NULL; ri = ri->next)
2292 if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0)
2293 continue;
2295 indent (e, ind + 2);
2297 switch (ri->type)
2299 default:
2300 abort ();
2302 case RCDATA_WORD:
2303 fprintf (e, "%d", ri->u.word);
2304 break;
2306 case RCDATA_DWORD:
2307 fprintf (e, "%luL", ri->u.dword);
2308 break;
2310 case RCDATA_STRING:
2312 const char *s;
2313 unsigned long i;
2315 fprintf (e, "\"");
2316 s = ri->u.string.s;
2317 for (i = 0; i < ri->u.string.length; i++)
2319 if (ISPRINT (*s))
2320 putc (*s, e);
2321 else
2322 fprintf (e, "\\%03o", *s);
2324 fprintf (e, "\"");
2325 break;
2328 case RCDATA_WSTRING:
2329 fprintf (e, "L\"");
2330 unicode_print (e, ri->u.wstring.w, ri->u.wstring.length);
2331 fprintf (e, "\"");
2332 break;
2334 case RCDATA_BUFFER:
2336 unsigned long i;
2337 int first;
2339 /* Assume little endian data. */
2341 first = 1;
2342 for (i = 0; i + 3 < ri->u.buffer.length; i += 4)
2344 unsigned long l;
2345 int j;
2347 if (! first)
2348 indent (e, ind + 2);
2349 l = ((((((ri->u.buffer.data[i + 3] << 8)
2350 | ri->u.buffer.data[i + 2]) << 8)
2351 | ri->u.buffer.data[i + 1]) << 8)
2352 | ri->u.buffer.data[i]);
2353 fprintf (e, "%luL", l);
2354 if (i + 4 < ri->u.buffer.length || ri->next != NULL)
2355 fprintf (e, ",");
2356 for (j = 0; j < 4; ++j)
2357 if (! ISPRINT (ri->u.buffer.data[i + j])
2358 && ri->u.buffer.data[i + j] != 0)
2359 break;
2360 if (j >= 4)
2362 fprintf (e, "\t// ");
2363 for (j = 0; j < 4; ++j)
2365 if (! ISPRINT (ri->u.buffer.data[i + j]))
2366 fprintf (e, "\\%03o", ri->u.buffer.data[i + j]);
2367 else
2369 if (ri->u.buffer.data[i + j] == '\\')
2370 fprintf (e, "\\");
2371 fprintf (e, "%c", ri->u.buffer.data[i + j]);
2375 fprintf (e, "\n");
2376 first = 0;
2379 if (i + 1 < ri->u.buffer.length)
2381 int s;
2382 int j;
2384 if (! first)
2385 indent (e, ind + 2);
2386 s = (ri->u.buffer.data[i + 1] << 8) | ri->u.buffer.data[i];
2387 fprintf (e, "%d", s);
2388 if (i + 2 < ri->u.buffer.length || ri->next != NULL)
2389 fprintf (e, ",");
2390 for (j = 0; j < 2; ++j)
2391 if (! ISPRINT (ri->u.buffer.data[i + j])
2392 && ri->u.buffer.data[i + j] != 0)
2393 break;
2394 if (j >= 2)
2396 fprintf (e, "\t// ");
2397 for (j = 0; j < 2; ++j)
2399 if (! ISPRINT (ri->u.buffer.data[i + j]))
2400 fprintf (e, "\\%03o", ri->u.buffer.data[i + j]);
2401 else
2403 if (ri->u.buffer.data[i + j] == '\\')
2404 fprintf (e, "\\");
2405 fprintf (e, "%c", ri->u.buffer.data[i + j]);
2409 fprintf (e, "\n");
2410 i += 2;
2411 first = 0;
2414 if (i < ri->u.buffer.length)
2416 if (! first)
2417 indent (e, ind + 2);
2418 if ((ri->u.buffer.data[i] & 0x7f) == ri->u.buffer.data[i]
2419 && ISPRINT (ri->u.buffer.data[i]))
2420 fprintf (e, "\"%c\"", ri->u.buffer.data[i]);
2421 else
2422 fprintf (e, "\"\\%03o\"", ri->u.buffer.data[i]);
2423 if (ri->next != NULL)
2424 fprintf (e, ",");
2425 fprintf (e, "\n");
2426 first = 0;
2429 break;
2433 if (ri->type != RCDATA_BUFFER)
2435 if (ri->next != NULL)
2436 fprintf (e, ",");
2437 fprintf (e, "\n");
2441 indent (e, ind);
2442 fprintf (e, "END\n");
2445 /* Write out a stringtable resource. */
2447 static void
2448 write_rc_stringtable (FILE *e, const struct res_id *name,
2449 const struct stringtable *stringtable)
2451 unsigned long offset;
2452 int i;
2454 if (name != NULL && ! name->named)
2455 offset = (name->u.id - 1) << 4;
2456 else
2458 fprintf (e, "// %s string table name\n",
2459 name == NULL ? "Missing" : "Invalid");
2460 offset = 0;
2463 fprintf (e, "BEGIN\n");
2465 for (i = 0; i < 16; i++)
2467 if (stringtable->strings[i].length != 0)
2469 fprintf (e, " %lu, \"", offset + i);
2470 unicode_print (e, stringtable->strings[i].string,
2471 stringtable->strings[i].length);
2472 fprintf (e, "\"\n");
2476 fprintf (e, "END\n");
2479 /* Write out a versioninfo resource. */
2481 static void
2482 write_rc_versioninfo (FILE *e, const struct versioninfo *versioninfo)
2484 const struct fixed_versioninfo *f;
2485 const struct ver_info *vi;
2487 f = versioninfo->fixed;
2488 if (f->file_version_ms != 0 || f->file_version_ls != 0)
2489 fprintf (e, " FILEVERSION %lu, %lu, %lu, %lu\n",
2490 (f->file_version_ms >> 16) & 0xffff,
2491 f->file_version_ms & 0xffff,
2492 (f->file_version_ls >> 16) & 0xffff,
2493 f->file_version_ls & 0xffff);
2494 if (f->product_version_ms != 0 || f->product_version_ls != 0)
2495 fprintf (e, " PRODUCTVERSION %lu, %lu, %lu, %lu\n",
2496 (f->product_version_ms >> 16) & 0xffff,
2497 f->product_version_ms & 0xffff,
2498 (f->product_version_ls >> 16) & 0xffff,
2499 f->product_version_ls & 0xffff);
2500 if (f->file_flags_mask != 0)
2501 fprintf (e, " FILEFLAGSMASK 0x%lx\n", f->file_flags_mask);
2502 if (f->file_flags != 0)
2503 fprintf (e, " FILEFLAGS 0x%lx\n", f->file_flags);
2504 if (f->file_os != 0)
2505 fprintf (e, " FILEOS 0x%lx\n", f->file_os);
2506 if (f->file_type != 0)
2507 fprintf (e, " FILETYPE 0x%lx\n", f->file_type);
2508 if (f->file_subtype != 0)
2509 fprintf (e, " FILESUBTYPE 0x%lx\n", f->file_subtype);
2510 if (f->file_date_ms != 0 || f->file_date_ls != 0)
2511 fprintf (e, "// Date: %lu, %lu\n", f->file_date_ms, f->file_date_ls);
2513 fprintf (e, "BEGIN\n");
2515 for (vi = versioninfo->var; vi != NULL; vi = vi->next)
2517 switch (vi->type)
2519 case VERINFO_STRING:
2521 const struct ver_stringinfo *vs;
2523 fprintf (e, " BLOCK \"StringFileInfo\"\n");
2524 fprintf (e, " BEGIN\n");
2525 fprintf (e, " BLOCK \"");
2526 unicode_print (e, vi->u.string.language, -1);
2527 fprintf (e, "\"\n");
2528 fprintf (e, " BEGIN\n");
2530 for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
2532 fprintf (e, " VALUE \"");
2533 unicode_print (e, vs->key, -1);
2534 fprintf (e, "\", \"");
2535 unicode_print (e, vs->value, -1);
2536 fprintf (e, "\"\n");
2539 fprintf (e, " END\n");
2540 fprintf (e, " END\n");
2541 break;
2544 case VERINFO_VAR:
2546 const struct ver_varinfo *vv;
2548 fprintf (e, " BLOCK \"VarFileInfo\"\n");
2549 fprintf (e, " BEGIN\n");
2550 fprintf (e, " VALUE \"");
2551 unicode_print (e, vi->u.var.key, -1);
2552 fprintf (e, "\"");
2554 for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
2555 fprintf (e, ", 0x%x, %d", (unsigned int) vv->language,
2556 vv->charset);
2558 fprintf (e, "\n END\n");
2560 break;
2565 fprintf (e, "END\n");
2568 /* Write out data which would normally be read from a file. */
2570 static void
2571 write_rc_filedata (FILE *e, unsigned long length, const unsigned char *data)
2573 unsigned long i;
2575 for (i = 0; i + 15 < length; i += 16)
2577 fprintf (e, "// %4lx: ", i);
2578 fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x ",
2579 data[i + 0], data[i + 1], data[i + 2], data[i + 3],
2580 data[i + 4], data[i + 5], data[i + 6], data[i + 7]);
2581 fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
2582 data[i + 8], data[i + 9], data[i + 10], data[i + 11],
2583 data[i + 12], data[i + 13], data[i + 14], data[i + 15]);
2586 if (i < length)
2588 fprintf (e, "// %4lx:", i);
2589 while (i < length)
2591 fprintf (e, " %02x", data[i]);
2592 ++i;
2594 fprintf (e, "\n");