* doc/c-xtensa.texi (Xtensa Automatic Alignment): Remove statements
[binutils.git] / binutils / resrc.c
blob0ec2875947bec4bb6cb83182c0ea2be193003701
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.
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 "sysdep.h"
27 #include "bfd.h"
28 #include "libiberty.h"
29 #include "safe-ctype.h"
30 #include "bucomm.h"
31 #include "windres.h"
33 #include <assert.h>
34 #include <sys/stat.h>
36 #ifdef HAVE_SYS_WAIT_H
37 #include <sys/wait.h>
38 #else /* ! HAVE_SYS_WAIT_H */
39 #if ! defined (_WIN32) || defined (__CYGWIN__)
40 #ifndef WIFEXITED
41 #define WIFEXITED(w) (((w)&0377) == 0)
42 #endif
43 #ifndef WIFSIGNALED
44 #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
45 #endif
46 #ifndef WTERMSIG
47 #define WTERMSIG(w) ((w) & 0177)
48 #endif
49 #ifndef WEXITSTATUS
50 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
51 #endif
52 #else /* defined (_WIN32) && ! defined (__CYGWIN__) */
53 #ifndef WIFEXITED
54 #define WIFEXITED(w) (((w) & 0xff) == 0)
55 #endif
56 #ifndef WIFSIGNALED
57 #define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
58 #endif
59 #ifndef WTERMSIG
60 #define WTERMSIG(w) ((w) & 0x7f)
61 #endif
62 #ifndef WEXITSTATUS
63 #define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
64 #endif
65 #endif /* defined (_WIN32) && ! defined (__CYGWIN__) */
66 #endif /* ! HAVE_SYS_WAIT_H */
68 #ifndef STDOUT_FILENO
69 #define STDOUT_FILENO 1
70 #endif
72 #if defined (_WIN32) && ! defined (__CYGWIN__)
73 #define popen _popen
74 #define pclose _pclose
75 #endif
77 /* The default preprocessor. */
79 #define DEFAULT_PREPROCESSOR "gcc -E -xc -DRC_INVOKED"
81 /* We read the directory entries in a cursor or icon file into
82 instances of this structure. */
84 struct icondir
86 /* Width of image. */
87 unsigned char width;
88 /* Height of image. */
89 unsigned char height;
90 /* Number of colors in image. */
91 unsigned char colorcount;
92 union
94 struct
96 /* Color planes. */
97 unsigned short planes;
98 /* Bits per pixel. */
99 unsigned short bits;
100 } icon;
101 struct
103 /* X coordinate of hotspot. */
104 unsigned short xhotspot;
105 /* Y coordinate of hotspot. */
106 unsigned short yhotspot;
107 } cursor;
108 } u;
109 /* Bytes in image. */
110 unsigned long bytes;
111 /* File offset of image. */
112 unsigned long offset;
115 /* The name of the rc file we are reading. */
117 char *rc_filename;
119 /* The line number in the rc file. */
121 int rc_lineno;
123 /* The pipe we are reading from, so that we can close it if we exit. */
125 static FILE *cpp_pipe;
127 /* The temporary file used if we're not using popen, so we can delete it
128 if we exit. */
130 static char *cpp_temp_file;
132 /* Input stream is either a file or a pipe. */
134 static enum {ISTREAM_PIPE, ISTREAM_FILE} istream_type;
136 /* As we read the rc file, we attach information to this structure. */
138 static struct res_directory *resources;
140 /* The number of cursor resources we have written out. */
142 static int cursors;
144 /* The number of font resources we have written out. */
146 static int fonts;
148 /* Font directory information. */
150 struct fontdir *fontdirs;
152 /* Resource info to use for fontdirs. */
154 struct res_res_info fontdirs_resinfo;
156 /* The number of icon resources we have written out. */
158 static int icons;
160 /* Local functions. */
162 static int run_cmd (char *, const char *);
163 static FILE *open_input_stream (char *);
164 static FILE *look_for_default
165 (char *, const char *, int, const char *, const char *);
166 static void close_input_stream (void);
167 static void unexpected_eof (const char *);
168 static int get_word (FILE *, const char *);
169 static unsigned long get_long (FILE *, const char *);
170 static void get_data (FILE *, unsigned char *, unsigned long, const char *);
171 static void define_fontdirs (void);
173 /* Run `cmd' and redirect the output to `redir'. */
175 static int
176 run_cmd (char *cmd, const char *redir)
178 char *s;
179 int pid, wait_status, retcode;
180 int i;
181 const char **argv;
182 char *errmsg_fmt, *errmsg_arg;
183 char *temp_base = choose_temp_base ();
184 int in_quote;
185 char sep;
186 int redir_handle = -1;
187 int stdout_save = -1;
189 /* Count the args. */
190 i = 0;
192 for (s = cmd; *s; s++)
193 if (*s == ' ')
194 i++;
196 i++;
197 argv = alloca (sizeof (char *) * (i + 3));
198 i = 0;
199 s = cmd;
201 while (1)
203 while (*s == ' ' && *s != 0)
204 s++;
206 if (*s == 0)
207 break;
209 in_quote = (*s == '\'' || *s == '"');
210 sep = (in_quote) ? *s++ : ' ';
211 argv[i++] = s;
213 while (*s != sep && *s != 0)
214 s++;
216 if (*s == 0)
217 break;
219 *s++ = 0;
221 if (in_quote)
222 s++;
224 argv[i++] = NULL;
226 /* Setup the redirection. We can't use the usual fork/exec and redirect
227 since we may be running on non-POSIX Windows host. */
229 fflush (stdout);
230 fflush (stderr);
232 /* Open temporary output file. */
233 redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT, 0666);
234 if (redir_handle == -1)
235 fatal (_("can't open temporary file `%s': %s"), redir,
236 strerror (errno));
238 /* Duplicate the stdout file handle so it can be restored later. */
239 stdout_save = dup (STDOUT_FILENO);
240 if (stdout_save == -1)
241 fatal (_("can't redirect stdout: `%s': %s"), redir, strerror (errno));
243 /* Redirect stdout to our output file. */
244 dup2 (redir_handle, STDOUT_FILENO);
246 pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
247 &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
249 /* Restore stdout to its previous setting. */
250 dup2 (stdout_save, STDOUT_FILENO);
252 /* Close response file. */
253 close (redir_handle);
255 if (pid == -1)
257 fatal (_("%s %s: %s"), errmsg_fmt, errmsg_arg, strerror (errno));
258 return 1;
261 retcode = 0;
262 pid = pwait (pid, &wait_status, 0);
264 if (pid == -1)
266 fatal (_("wait: %s"), strerror (errno));
267 retcode = 1;
269 else if (WIFSIGNALED (wait_status))
271 fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
272 retcode = 1;
274 else if (WIFEXITED (wait_status))
276 if (WEXITSTATUS (wait_status) != 0)
278 fatal (_("%s exited with status %d"), cmd,
279 WEXITSTATUS (wait_status));
280 retcode = 1;
283 else
284 retcode = 1;
286 return retcode;
289 static FILE *
290 open_input_stream (char *cmd)
292 if (istream_type == ISTREAM_FILE)
294 char *fileprefix;
296 fileprefix = choose_temp_base ();
297 cpp_temp_file = (char *) xmalloc (strlen (fileprefix) + 5);
298 sprintf (cpp_temp_file, "%s.irc", fileprefix);
299 free (fileprefix);
301 if (run_cmd (cmd, cpp_temp_file))
302 fatal (_("can't execute `%s': %s"), cmd, strerror (errno));
304 cpp_pipe = fopen (cpp_temp_file, FOPEN_RT);;
305 if (cpp_pipe == NULL)
306 fatal (_("can't open temporary file `%s': %s"),
307 cpp_temp_file, strerror (errno));
309 if (verbose)
310 fprintf (stderr,
311 _("Using temporary file `%s' to read preprocessor output\n"),
312 cpp_temp_file);
314 else
316 cpp_pipe = popen (cmd, FOPEN_RT);
317 if (cpp_pipe == NULL)
318 fatal (_("can't popen `%s': %s"), cmd, strerror (errno));
319 if (verbose)
320 fprintf (stderr, _("Using popen to read preprocessor output\n"));
323 xatexit (close_input_stream);
324 return cpp_pipe;
327 /* look for the preprocessor program */
329 static FILE *
330 look_for_default (char *cmd, const char *prefix, int end_prefix,
331 const char *preprocargs, const char *filename)
333 char *space;
334 int found;
335 struct stat s;
337 strcpy (cmd, prefix);
339 sprintf (cmd + end_prefix, "%s", DEFAULT_PREPROCESSOR);
340 space = strchr (cmd + end_prefix, ' ');
341 if (space)
342 *space = 0;
344 if (
345 #if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32)
346 strchr (cmd, '\\') ||
347 #endif
348 strchr (cmd, '/'))
350 found = (stat (cmd, &s) == 0
351 #ifdef HAVE_EXECUTABLE_SUFFIX
352 || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
353 #endif
356 if (! found)
358 if (verbose)
359 fprintf (stderr, _("Tried `%s'\n"), cmd);
360 return NULL;
364 strcpy (cmd, prefix);
366 sprintf (cmd + end_prefix, "%s %s %s",
367 DEFAULT_PREPROCESSOR, preprocargs, filename);
369 if (verbose)
370 fprintf (stderr, _("Using `%s'\n"), cmd);
372 cpp_pipe = open_input_stream (cmd);
373 return cpp_pipe;
376 /* Read an rc file. */
378 struct res_directory *
379 read_rc_file (const char *filename, const char *preprocessor,
380 const char *preprocargs, int language, int use_temp_file)
382 char *cmd;
384 istream_type = (use_temp_file) ? ISTREAM_FILE : ISTREAM_PIPE;
386 if (preprocargs == NULL)
387 preprocargs = "";
388 if (filename == NULL)
389 filename = "-";
391 if (preprocessor)
393 cmd = xmalloc (strlen (preprocessor)
394 + strlen (preprocargs)
395 + strlen (filename)
396 + 10);
397 sprintf (cmd, "%s %s %s", preprocessor, preprocargs, filename);
399 cpp_pipe = open_input_stream (cmd);
401 else
403 char *dash, *slash, *cp;
405 preprocessor = DEFAULT_PREPROCESSOR;
407 cmd = xmalloc (strlen (program_name)
408 + strlen (preprocessor)
409 + strlen (preprocargs)
410 + strlen (filename)
411 #ifdef HAVE_EXECUTABLE_SUFFIX
412 + strlen (EXECUTABLE_SUFFIX)
413 #endif
414 + 10);
417 dash = slash = 0;
418 for (cp = program_name; *cp; cp++)
420 if (*cp == '-')
421 dash = cp;
422 if (
423 #if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32)
424 *cp == ':' || *cp == '\\' ||
425 #endif
426 *cp == '/')
428 slash = cp;
429 dash = 0;
433 cpp_pipe = 0;
435 if (dash)
437 /* First, try looking for a prefixed gcc in the windres
438 directory, with the same prefix as windres */
440 cpp_pipe = look_for_default (cmd, program_name, dash-program_name+1,
441 preprocargs, filename);
444 if (slash && !cpp_pipe)
446 /* Next, try looking for a gcc in the same directory as
447 that windres */
449 cpp_pipe = look_for_default (cmd, program_name, slash-program_name+1,
450 preprocargs, filename);
453 if (!cpp_pipe)
455 /* Sigh, try the default */
457 cpp_pipe = look_for_default (cmd, "", 0, preprocargs, filename);
462 free (cmd);
464 rc_filename = xstrdup (filename);
465 rc_lineno = 1;
466 if (language != -1)
467 rcparse_set_language (language);
468 yyin = cpp_pipe;
469 yyparse ();
470 rcparse_discard_strings ();
472 close_input_stream ();
474 if (fontdirs != NULL)
475 define_fontdirs ();
477 free (rc_filename);
478 rc_filename = NULL;
480 return resources;
483 /* Close the input stream if it is open. */
485 static void
486 close_input_stream (void)
488 if (istream_type == ISTREAM_FILE)
490 if (cpp_pipe != NULL)
491 fclose (cpp_pipe);
493 if (cpp_temp_file != NULL)
495 int errno_save = errno;
497 unlink (cpp_temp_file);
498 errno = errno_save;
499 free (cpp_temp_file);
502 else
504 if (cpp_pipe != NULL)
505 pclose (cpp_pipe);
508 /* Since this is also run via xatexit, safeguard. */
509 cpp_pipe = NULL;
510 cpp_temp_file = NULL;
513 /* Report an error while reading an rc file. */
515 void
516 yyerror (const char *msg)
518 fatal ("%s:%d: %s", rc_filename, rc_lineno, msg);
521 /* Issue a warning while reading an rc file. */
523 void
524 rcparse_warning (const char *msg)
526 fprintf (stderr, _("%s:%d: %s\n"), rc_filename, rc_lineno, msg);
529 /* Die if we get an unexpected end of file. */
531 static void
532 unexpected_eof (const char *msg)
534 fatal (_("%s: unexpected EOF"), msg);
537 /* Read a 16 bit word from a file. The data is assumed to be little
538 endian. */
540 static int
541 get_word (FILE *e, const char *msg)
543 int b1, b2;
545 b1 = getc (e);
546 b2 = getc (e);
547 if (feof (e))
548 unexpected_eof (msg);
549 return ((b2 & 0xff) << 8) | (b1 & 0xff);
552 /* Read a 32 bit word from a file. The data is assumed to be little
553 endian. */
555 static unsigned long
556 get_long (FILE *e, const char *msg)
558 int b1, b2, b3, b4;
560 b1 = getc (e);
561 b2 = getc (e);
562 b3 = getc (e);
563 b4 = getc (e);
564 if (feof (e))
565 unexpected_eof (msg);
566 return (((((((b4 & 0xff) << 8)
567 | (b3 & 0xff)) << 8)
568 | (b2 & 0xff)) << 8)
569 | (b1 & 0xff));
572 /* Read data from a file. This is a wrapper to do error checking. */
574 static void
575 get_data (FILE *e, unsigned char *p, unsigned long c, const char *msg)
577 unsigned long got;
579 got = fread (p, 1, c, e);
580 if (got == c)
581 return;
583 fatal (_("%s: read of %lu returned %lu"), msg, c, got);
586 /* Define an accelerator resource. */
588 void
589 define_accelerator (struct res_id id, const struct res_res_info *resinfo,
590 struct accelerator *data)
592 struct res_resource *r;
594 r = define_standard_resource (&resources, RT_ACCELERATOR, id,
595 resinfo->language, 0);
596 r->type = RES_TYPE_ACCELERATOR;
597 r->u.acc = data;
598 r->res_info = *resinfo;
601 /* Define a bitmap resource. Bitmap data is stored in a file. The
602 first 14 bytes of the file are a standard header, which is not
603 included in the resource data. */
605 #define BITMAP_SKIP (14)
607 void
608 define_bitmap (struct res_id id, const struct res_res_info *resinfo,
609 const char *filename)
611 FILE *e;
612 char *real_filename;
613 struct stat s;
614 unsigned char *data;
615 int i;
616 struct res_resource *r;
618 e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename);
620 if (stat (real_filename, &s) < 0)
621 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
622 strerror (errno));
624 data = (unsigned char *) res_alloc (s.st_size - BITMAP_SKIP);
626 for (i = 0; i < BITMAP_SKIP; i++)
627 getc (e);
629 get_data (e, data, s.st_size - BITMAP_SKIP, real_filename);
631 fclose (e);
632 free (real_filename);
634 r = define_standard_resource (&resources, RT_BITMAP, id,
635 resinfo->language, 0);
637 r->type = RES_TYPE_BITMAP;
638 r->u.data.length = s.st_size - BITMAP_SKIP;
639 r->u.data.data = data;
640 r->res_info = *resinfo;
643 /* Define a cursor resource. A cursor file may contain a set of
644 bitmaps, each representing the same cursor at various different
645 resolutions. They each get written out with a different ID. The
646 real cursor resource is then a group resource which can be used to
647 select one of the actual cursors. */
649 void
650 define_cursor (struct res_id id, const struct res_res_info *resinfo,
651 const char *filename)
653 FILE *e;
654 char *real_filename;
655 int type, count, i;
656 struct icondir *icondirs;
657 int first_cursor;
658 struct res_resource *r;
659 struct group_cursor *first, **pp;
661 e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename);
663 /* A cursor file is basically an icon file. The start of the file
664 is a three word structure. The first word is ignored. The
665 second word is the type of data. The third word is the number of
666 entries. */
668 get_word (e, real_filename);
669 type = get_word (e, real_filename);
670 count = get_word (e, real_filename);
671 if (type != 2)
672 fatal (_("cursor file `%s' does not contain cursor data"), real_filename);
674 /* Read in the icon directory entries. */
676 icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
678 for (i = 0; i < count; i++)
680 icondirs[i].width = getc (e);
681 icondirs[i].height = getc (e);
682 icondirs[i].colorcount = getc (e);
683 getc (e);
684 icondirs[i].u.cursor.xhotspot = get_word (e, real_filename);
685 icondirs[i].u.cursor.yhotspot = get_word (e, real_filename);
686 icondirs[i].bytes = get_long (e, real_filename);
687 icondirs[i].offset = get_long (e, real_filename);
689 if (feof (e))
690 unexpected_eof (real_filename);
693 /* Define each cursor as a unique resource. */
695 first_cursor = cursors;
697 for (i = 0; i < count; i++)
699 unsigned char *data;
700 struct res_id name;
701 struct cursor *c;
703 if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
704 fatal (_("%s: fseek to %lu failed: %s"), real_filename,
705 icondirs[i].offset, strerror (errno));
707 data = (unsigned char *) res_alloc (icondirs[i].bytes);
709 get_data (e, data, icondirs[i].bytes, real_filename);
711 c = (struct cursor *) res_alloc (sizeof *c);
712 c->xhotspot = icondirs[i].u.cursor.xhotspot;
713 c->yhotspot = icondirs[i].u.cursor.yhotspot;
714 c->length = icondirs[i].bytes;
715 c->data = data;
717 ++cursors;
719 name.named = 0;
720 name.u.id = cursors;
722 r = define_standard_resource (&resources, RT_CURSOR, name,
723 resinfo->language, 0);
724 r->type = RES_TYPE_CURSOR;
725 r->u.cursor = c;
726 r->res_info = *resinfo;
729 fclose (e);
730 free (real_filename);
732 /* Define a cursor group resource. */
734 first = NULL;
735 pp = &first;
736 for (i = 0; i < count; i++)
738 struct group_cursor *cg;
740 cg = (struct group_cursor *) res_alloc (sizeof *cg);
741 cg->next = NULL;
742 cg->width = icondirs[i].width;
743 cg->height = 2 * icondirs[i].height;
745 /* FIXME: What should these be set to? */
746 cg->planes = 1;
747 cg->bits = 1;
749 cg->bytes = icondirs[i].bytes + 4;
750 cg->index = first_cursor + i + 1;
752 *pp = cg;
753 pp = &(*pp)->next;
756 free (icondirs);
758 r = define_standard_resource (&resources, RT_GROUP_CURSOR, id,
759 resinfo->language, 0);
760 r->type = RES_TYPE_GROUP_CURSOR;
761 r->u.group_cursor = first;
762 r->res_info = *resinfo;
765 /* Define a dialog resource. */
767 void
768 define_dialog (struct res_id id, const struct res_res_info *resinfo,
769 const struct dialog *dialog)
771 struct dialog *copy;
772 struct res_resource *r;
774 copy = (struct dialog *) res_alloc (sizeof *copy);
775 *copy = *dialog;
777 r = define_standard_resource (&resources, RT_DIALOG, id,
778 resinfo->language, 0);
779 r->type = RES_TYPE_DIALOG;
780 r->u.dialog = copy;
781 r->res_info = *resinfo;
784 /* Define a dialog control. This does not define a resource, but
785 merely allocates and fills in a structure. */
787 struct dialog_control *
788 define_control (const struct res_id iid, unsigned long id, unsigned long x,
789 unsigned long y, unsigned long width, unsigned long height,
790 unsigned long class, unsigned long style,
791 unsigned long exstyle)
793 struct dialog_control *n;
795 n = (struct dialog_control *) res_alloc (sizeof *n);
796 n->next = NULL;
797 n->id = id;
798 n->style = style;
799 n->exstyle = exstyle;
800 n->x = x;
801 n->y = y;
802 n->width = width;
803 n->height = height;
804 n->class.named = 0;
805 n->class.u.id = class;
806 n->text = iid;
807 n->data = NULL;
808 n->help = 0;
810 return n;
813 struct dialog_control *
814 define_icon_control (struct res_id iid, unsigned long id, unsigned long x,
815 unsigned long y, unsigned long style,
816 unsigned long exstyle, unsigned long help,
817 struct rcdata_item *data, struct dialog_ex *ex)
819 struct dialog_control *n;
820 struct res_id tid;
822 if (style == 0)
823 style = SS_ICON | WS_CHILD | WS_VISIBLE;
824 res_string_to_id (&tid, "");
825 n = define_control (tid, id, x, y, 0, 0, CTL_STATIC, style, exstyle);
826 n->text = iid;
827 if (help && !ex)
828 rcparse_warning (_("help ID requires DIALOGEX"));
829 if (data && !ex)
830 rcparse_warning (_("control data requires DIALOGEX"));
831 n->help = help;
832 n->data = data;
834 return n;
837 /* Define a font resource. */
839 void
840 define_font (struct res_id id, const struct res_res_info *resinfo,
841 const char *filename)
843 FILE *e;
844 char *real_filename;
845 struct stat s;
846 unsigned char *data;
847 struct res_resource *r;
848 long offset;
849 long fontdatalength;
850 unsigned char *fontdata;
851 struct fontdir *fd;
852 const char *device, *face;
853 struct fontdir **pp;
855 e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
857 if (stat (real_filename, &s) < 0)
858 fatal (_("stat failed on font file `%s': %s"), real_filename,
859 strerror (errno));
861 data = (unsigned char *) res_alloc (s.st_size);
863 get_data (e, data, s.st_size, real_filename);
865 fclose (e);
866 free (real_filename);
868 r = define_standard_resource (&resources, RT_FONT, id,
869 resinfo->language, 0);
871 r->type = RES_TYPE_FONT;
872 r->u.data.length = s.st_size;
873 r->u.data.data = data;
874 r->res_info = *resinfo;
876 /* For each font resource, we must add an entry in the FONTDIR
877 resource. The FONTDIR resource includes some strings in the font
878 file. To find them, we have to do some magic on the data we have
879 read. */
881 offset = ((((((data[47] << 8)
882 | data[46]) << 8)
883 | data[45]) << 8)
884 | data[44]);
885 if (offset > 0 && offset < s.st_size)
886 device = (char *) data + offset;
887 else
888 device = "";
890 offset = ((((((data[51] << 8)
891 | data[50]) << 8)
892 | data[49]) << 8)
893 | data[48]);
894 if (offset > 0 && offset < s.st_size)
895 face = (char *) data + offset;
896 else
897 face = "";
899 ++fonts;
901 fontdatalength = 58 + strlen (device) + strlen (face);
902 fontdata = (unsigned char *) res_alloc (fontdatalength);
903 memcpy (fontdata, data, 56);
904 strcpy ((char *) fontdata + 56, device);
905 strcpy ((char *) fontdata + 57 + strlen (device), face);
907 fd = (struct fontdir *) res_alloc (sizeof *fd);
908 fd->next = NULL;
909 fd->index = fonts;
910 fd->length = fontdatalength;
911 fd->data = fontdata;
913 for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next)
915 *pp = fd;
917 /* For the single fontdirs resource, we always use the resource
918 information of the last font. I don't know what else to do. */
919 fontdirs_resinfo = *resinfo;
922 /* Define the fontdirs resource. This is called after the entire rc
923 file has been parsed, if any font resources were seen. */
925 static void
926 define_fontdirs (void)
928 struct res_resource *r;
929 struct res_id id;
931 id.named = 0;
932 id.u.id = 1;
934 r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
936 r->type = RES_TYPE_FONTDIR;
937 r->u.fontdir = fontdirs;
938 r->res_info = fontdirs_resinfo;
941 /* Define an icon resource. An icon file may contain a set of
942 bitmaps, each representing the same icon at various different
943 resolutions. They each get written out with a different ID. The
944 real icon resource is then a group resource which can be used to
945 select one of the actual icon bitmaps. */
947 void
948 define_icon (struct res_id id, const struct res_res_info *resinfo,
949 const char *filename)
951 FILE *e;
952 char *real_filename;
953 int type, count, i;
954 struct icondir *icondirs;
955 int first_icon;
956 struct res_resource *r;
957 struct group_icon *first, **pp;
959 e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename);
961 /* The start of an icon file is a three word structure. The first
962 word is ignored. The second word is the type of data. The third
963 word is the number of entries. */
965 get_word (e, real_filename);
966 type = get_word (e, real_filename);
967 count = get_word (e, real_filename);
968 if (type != 1)
969 fatal (_("icon file `%s' does not contain icon data"), real_filename);
971 /* Read in the icon directory entries. */
973 icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
975 for (i = 0; i < count; i++)
977 icondirs[i].width = getc (e);
978 icondirs[i].height = getc (e);
979 icondirs[i].colorcount = getc (e);
980 getc (e);
981 icondirs[i].u.icon.planes = get_word (e, real_filename);
982 icondirs[i].u.icon.bits = get_word (e, real_filename);
983 icondirs[i].bytes = get_long (e, real_filename);
984 icondirs[i].offset = get_long (e, real_filename);
986 if (feof (e))
987 unexpected_eof (real_filename);
990 /* Define each icon as a unique resource. */
992 first_icon = icons;
994 for (i = 0; i < count; i++)
996 unsigned char *data;
997 struct res_id name;
999 if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
1000 fatal (_("%s: fseek to %lu failed: %s"), real_filename,
1001 icondirs[i].offset, strerror (errno));
1003 data = (unsigned char *) res_alloc (icondirs[i].bytes);
1005 get_data (e, data, icondirs[i].bytes, real_filename);
1007 ++icons;
1009 name.named = 0;
1010 name.u.id = icons;
1012 r = define_standard_resource (&resources, RT_ICON, name,
1013 resinfo->language, 0);
1014 r->type = RES_TYPE_ICON;
1015 r->u.data.length = icondirs[i].bytes;
1016 r->u.data.data = data;
1017 r->res_info = *resinfo;
1020 fclose (e);
1021 free (real_filename);
1023 /* Define an icon group resource. */
1025 first = NULL;
1026 pp = &first;
1027 for (i = 0; i < count; i++)
1029 struct group_icon *cg;
1031 /* For some reason, at least in some files the planes and bits
1032 are zero. We instead set them from the color. This is
1033 copied from rcl. */
1035 cg = (struct group_icon *) res_alloc (sizeof *cg);
1036 cg->next = NULL;
1037 cg->width = icondirs[i].width;
1038 cg->height = icondirs[i].height;
1039 cg->colors = icondirs[i].colorcount;
1041 if (icondirs[i].u.icon.planes)
1042 cg->planes = icondirs[i].u.icon.planes;
1043 else
1044 cg->planes = 1;
1046 if (icondirs[i].u.icon.bits)
1047 cg->bits = icondirs[i].u.icon.bits;
1048 else
1050 cg->bits = 0;
1052 while ((1L << cg->bits) < cg->colors)
1053 ++cg->bits;
1056 cg->bytes = icondirs[i].bytes;
1057 cg->index = first_icon + i + 1;
1059 *pp = cg;
1060 pp = &(*pp)->next;
1063 free (icondirs);
1065 r = define_standard_resource (&resources, RT_GROUP_ICON, id,
1066 resinfo->language, 0);
1067 r->type = RES_TYPE_GROUP_ICON;
1068 r->u.group_icon = first;
1069 r->res_info = *resinfo;
1072 /* Define a menu resource. */
1074 void
1075 define_menu (struct res_id id, const struct res_res_info *resinfo,
1076 struct menuitem *menuitems)
1078 struct menu *m;
1079 struct res_resource *r;
1081 m = (struct menu *) res_alloc (sizeof *m);
1082 m->items = menuitems;
1083 m->help = 0;
1085 r = define_standard_resource (&resources, RT_MENU, id, resinfo->language, 0);
1086 r->type = RES_TYPE_MENU;
1087 r->u.menu = m;
1088 r->res_info = *resinfo;
1091 /* Define a menu item. This does not define a resource, but merely
1092 allocates and fills in a structure. */
1094 struct menuitem *
1095 define_menuitem (const char *text, int menuid, unsigned long type,
1096 unsigned long state, unsigned long help,
1097 struct menuitem *menuitems)
1099 struct menuitem *mi;
1101 mi = (struct menuitem *) res_alloc (sizeof *mi);
1102 mi->next = NULL;
1103 mi->type = type;
1104 mi->state = state;
1105 mi->id = menuid;
1106 if (text == NULL)
1107 mi->text = NULL;
1108 else
1109 unicode_from_ascii ((int *) NULL, &mi->text, text);
1110 mi->help = help;
1111 mi->popup = menuitems;
1112 return mi;
1115 /* Define a messagetable resource. */
1117 void
1118 define_messagetable (struct res_id id, const struct res_res_info *resinfo,
1119 const char *filename)
1121 FILE *e;
1122 char *real_filename;
1123 struct stat s;
1124 unsigned char *data;
1125 struct res_resource *r;
1127 e = open_file_search (filename, FOPEN_RB, "messagetable file",
1128 &real_filename);
1130 if (stat (real_filename, &s) < 0)
1131 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
1132 strerror (errno));
1134 data = (unsigned char *) res_alloc (s.st_size);
1136 get_data (e, data, s.st_size, real_filename);
1138 fclose (e);
1139 free (real_filename);
1141 r = define_standard_resource (&resources, RT_MESSAGETABLE, id,
1142 resinfo->language, 0);
1144 r->type = RES_TYPE_MESSAGETABLE;
1145 r->u.data.length = s.st_size;
1146 r->u.data.data = data;
1147 r->res_info = *resinfo;
1150 /* Define an rcdata resource. */
1152 void
1153 define_rcdata (struct res_id id, const struct res_res_info *resinfo,
1154 struct rcdata_item *data)
1156 struct res_resource *r;
1158 r = define_standard_resource (&resources, RT_RCDATA, id,
1159 resinfo->language, 0);
1160 r->type = RES_TYPE_RCDATA;
1161 r->u.rcdata = data;
1162 r->res_info = *resinfo;
1165 /* Create an rcdata item holding a string. */
1167 struct rcdata_item *
1168 define_rcdata_string (const char *string, unsigned long len)
1170 struct rcdata_item *ri;
1171 char *s;
1173 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
1174 ri->next = NULL;
1175 ri->type = RCDATA_STRING;
1176 ri->u.string.length = len;
1177 s = (char *) res_alloc (len);
1178 memcpy (s, string, len);
1179 ri->u.string.s = s;
1181 return ri;
1184 /* Create an rcdata item holding a number. */
1186 struct rcdata_item *
1187 define_rcdata_number (unsigned long val, int dword)
1189 struct rcdata_item *ri;
1191 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
1192 ri->next = NULL;
1193 ri->type = dword ? RCDATA_DWORD : RCDATA_WORD;
1194 ri->u.word = val;
1196 return ri;
1199 /* Define a stringtable resource. This is called for each string
1200 which appears in a STRINGTABLE statement. */
1202 void
1203 define_stringtable (const struct res_res_info *resinfo,
1204 unsigned long stringid, const char *string)
1206 struct res_id id;
1207 struct res_resource *r;
1209 id.named = 0;
1210 id.u.id = (stringid >> 4) + 1;
1211 r = define_standard_resource (&resources, RT_STRING, id,
1212 resinfo->language, 1);
1214 if (r->type == RES_TYPE_UNINITIALIZED)
1216 int i;
1218 r->type = RES_TYPE_STRINGTABLE;
1219 r->u.stringtable = ((struct stringtable *)
1220 res_alloc (sizeof (struct stringtable)));
1221 for (i = 0; i < 16; i++)
1223 r->u.stringtable->strings[i].length = 0;
1224 r->u.stringtable->strings[i].string = NULL;
1227 r->res_info = *resinfo;
1230 unicode_from_ascii (&r->u.stringtable->strings[stringid & 0xf].length,
1231 &r->u.stringtable->strings[stringid & 0xf].string,
1232 string);
1235 /* Define a user data resource where the data is in the rc file. */
1237 void
1238 define_user_data (struct res_id id, struct res_id type,
1239 const struct res_res_info *resinfo,
1240 struct rcdata_item *data)
1242 struct res_id ids[3];
1243 struct res_resource *r;
1245 ids[0] = type;
1246 ids[1] = id;
1247 ids[2].named = 0;
1248 ids[2].u.id = resinfo->language;
1250 r = define_resource (& resources, 3, ids, 0);
1251 r->type = RES_TYPE_USERDATA;
1252 r->u.userdata = data;
1253 r->res_info = *resinfo;
1256 void
1257 define_rcdata_file (struct res_id id, const struct res_res_info *resinfo,
1258 const char *filename)
1260 struct rcdata_item *ri;
1261 FILE *e;
1262 char *real_filename;
1263 struct stat s;
1264 unsigned char *data;
1266 e = open_file_search (filename, FOPEN_RB, "file", &real_filename);
1269 if (stat (real_filename, &s) < 0)
1270 fatal (_("stat failed on file `%s': %s"), real_filename,
1271 strerror (errno));
1273 data = (unsigned char *) res_alloc (s.st_size);
1275 get_data (e, data, s.st_size, real_filename);
1277 fclose (e);
1278 free (real_filename);
1280 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
1281 ri->next = NULL;
1282 ri->type = RCDATA_BUFFER;
1283 ri->u.buffer.length = s.st_size;
1284 ri->u.buffer.data = data;
1286 define_rcdata (id, resinfo, ri);
1289 /* Define a user data resource where the data is in a file. */
1291 void
1292 define_user_file (struct res_id id, struct res_id type,
1293 const struct res_res_info *resinfo, const char *filename)
1295 FILE *e;
1296 char *real_filename;
1297 struct stat s;
1298 unsigned char *data;
1299 struct res_id ids[3];
1300 struct res_resource *r;
1302 e = open_file_search (filename, FOPEN_RB, "file", &real_filename);
1304 if (stat (real_filename, &s) < 0)
1305 fatal (_("stat failed on file `%s': %s"), real_filename,
1306 strerror (errno));
1308 data = (unsigned char *) res_alloc (s.st_size);
1310 get_data (e, data, s.st_size, real_filename);
1312 fclose (e);
1313 free (real_filename);
1315 ids[0] = type;
1316 ids[1] = id;
1317 ids[2].named = 0;
1318 ids[2].u.id = resinfo->language;
1320 r = define_resource (&resources, 3, ids, 0);
1321 r->type = RES_TYPE_USERDATA;
1322 r->u.userdata = ((struct rcdata_item *)
1323 res_alloc (sizeof (struct rcdata_item)));
1324 r->u.userdata->next = NULL;
1325 r->u.userdata->type = RCDATA_BUFFER;
1326 r->u.userdata->u.buffer.length = s.st_size;
1327 r->u.userdata->u.buffer.data = data;
1328 r->res_info = *resinfo;
1331 /* Define a versioninfo resource. */
1333 void
1334 define_versioninfo (struct res_id id, int language,
1335 struct fixed_versioninfo *fixedverinfo,
1336 struct ver_info *verinfo)
1338 struct res_resource *r;
1340 r = define_standard_resource (&resources, RT_VERSION, id, language, 0);
1341 r->type = RES_TYPE_VERSIONINFO;
1342 r->u.versioninfo = ((struct versioninfo *)
1343 res_alloc (sizeof (struct versioninfo)));
1344 r->u.versioninfo->fixed = fixedverinfo;
1345 r->u.versioninfo->var = verinfo;
1346 r->res_info.language = language;
1349 /* Add string version info to a list of version information. */
1351 struct ver_info *
1352 append_ver_stringfileinfo (struct ver_info *verinfo, const char *language,
1353 struct ver_stringinfo *strings)
1355 struct ver_info *vi, **pp;
1357 vi = (struct ver_info *) res_alloc (sizeof *vi);
1358 vi->next = NULL;
1359 vi->type = VERINFO_STRING;
1360 unicode_from_ascii ((int *) NULL, &vi->u.string.language, language);
1361 vi->u.string.strings = strings;
1363 for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1365 *pp = vi;
1367 return verinfo;
1370 /* Add variable version info to a list of version information. */
1372 struct ver_info *
1373 append_ver_varfileinfo (struct ver_info *verinfo, const char *key,
1374 struct ver_varinfo *var)
1376 struct ver_info *vi, **pp;
1378 vi = (struct ver_info *) res_alloc (sizeof *vi);
1379 vi->next = NULL;
1380 vi->type = VERINFO_VAR;
1381 unicode_from_ascii ((int *) NULL, &vi->u.var.key, key);
1382 vi->u.var.var = var;
1384 for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1386 *pp = vi;
1388 return verinfo;
1391 /* Append version string information to a list. */
1393 struct ver_stringinfo *
1394 append_verval (struct ver_stringinfo *strings, const char *key,
1395 const char *value)
1397 struct ver_stringinfo *vs, **pp;
1399 vs = (struct ver_stringinfo *) res_alloc (sizeof *vs);
1400 vs->next = NULL;
1401 unicode_from_ascii ((int *) NULL, &vs->key, key);
1402 unicode_from_ascii ((int *) NULL, &vs->value, value);
1404 for (pp = &strings; *pp != NULL; pp = &(*pp)->next)
1406 *pp = vs;
1408 return strings;
1411 /* Append version variable information to a list. */
1413 struct ver_varinfo *
1414 append_vertrans (struct ver_varinfo *var, unsigned long language,
1415 unsigned long charset)
1417 struct ver_varinfo *vv, **pp;
1419 vv = (struct ver_varinfo *) res_alloc (sizeof *vv);
1420 vv->next = NULL;
1421 vv->language = language;
1422 vv->charset = charset;
1424 for (pp = &var; *pp != NULL; pp = &(*pp)->next)
1426 *pp = vv;
1428 return var;
1431 /* Local functions used to write out an rc file. */
1433 static void indent (FILE *, int);
1434 static void write_rc_directory
1435 (FILE *, const struct res_directory *, const struct res_id *,
1436 const struct res_id *, int *, int);
1437 static void write_rc_subdir
1438 (FILE *, const struct res_entry *, const struct res_id *,
1439 const struct res_id *, int *, int);
1440 static void write_rc_resource
1441 (FILE *, const struct res_id *, const struct res_id *,
1442 const struct res_resource *, int *);
1443 static void write_rc_accelerators (FILE *, const struct accelerator *);
1444 static void write_rc_cursor (FILE *, const struct cursor *);
1445 static void write_rc_group_cursor (FILE *, const struct group_cursor *);
1446 static void write_rc_dialog (FILE *, const struct dialog *);
1447 static void write_rc_dialog_control (FILE *, const struct dialog_control *);
1448 static void write_rc_fontdir (FILE *, const struct fontdir *);
1449 static void write_rc_group_icon (FILE *, const struct group_icon *);
1450 static void write_rc_menu (FILE *, const struct menu *, int);
1451 static void write_rc_menuitems (FILE *, const struct menuitem *, int, int);
1452 static void write_rc_rcdata (FILE *, const struct rcdata_item *, int);
1453 static void write_rc_stringtable
1454 (FILE *, const struct res_id *, const struct stringtable *);
1455 static void write_rc_versioninfo (FILE *, const struct versioninfo *);
1456 static void write_rc_filedata (FILE *, unsigned long, const unsigned char *);
1458 /* Indent a given number of spaces. */
1460 static void
1461 indent (FILE *e, int c)
1463 int i;
1465 for (i = 0; i < c; i++)
1466 putc (' ', e);
1469 /* Dump the resources we have read in the format of an rc file.
1471 Actually, we don't use the format of an rc file, because it's way
1472 too much of a pain--for example, we'd have to write icon resources
1473 into a file and refer to that file. We just generate a readable
1474 format that kind of looks like an rc file, and is useful for
1475 understanding the contents of a resource file. Someday we may want
1476 to generate an rc file which the rc compiler can read; if that day
1477 comes, this code will have to be fixed up. */
1479 void
1480 write_rc_file (const char *filename, const struct res_directory *resources)
1482 FILE *e;
1483 int language;
1485 if (filename == NULL)
1486 e = stdout;
1487 else
1489 e = fopen (filename, FOPEN_WT);
1490 if (e == NULL)
1491 fatal (_("can't open `%s' for output: %s"), filename, strerror (errno));
1494 language = -1;
1495 write_rc_directory (e, resources, (const struct res_id *) NULL,
1496 (const struct res_id *) NULL, &language, 1);
1499 /* Write out a directory. E is the file to write to. RD is the
1500 directory. TYPE is a pointer to the level 1 ID which serves as the
1501 resource type. NAME is a pointer to the level 2 ID which serves as
1502 an individual resource name. LANGUAGE is a pointer to the current
1503 language. LEVEL is the level in the tree. */
1505 static void
1506 write_rc_directory (FILE *e, const struct res_directory *rd,
1507 const struct res_id *type, const struct res_id *name,
1508 int *language, int level)
1510 const struct res_entry *re;
1512 /* Print out some COFF information that rc files can't represent. */
1514 if (rd->time != 0)
1515 fprintf (e, "// Time stamp: %lu\n", rd->time);
1516 if (rd->characteristics != 0)
1517 fprintf (e, "// Characteristics: %lu\n", rd->characteristics);
1518 if (rd->major != 0 || rd->minor != 0)
1519 fprintf (e, "// Version: %d %d\n", rd->major, rd->minor);
1521 for (re = rd->entries; re != NULL; re = re->next)
1523 switch (level)
1525 case 1:
1526 /* If we're at level 1, the key of this resource is the
1527 type. This normally duplicates the information we have
1528 stored with the resource itself, but we need to remember
1529 the type if this is a user define resource type. */
1530 type = &re->id;
1531 break;
1533 case 2:
1534 /* If we're at level 2, the key of this resource is the name
1535 we are going to use in the rc printout. */
1536 name = &re->id;
1537 break;
1539 case 3:
1540 /* If we're at level 3, then this key represents a language.
1541 Use it to update the current language. */
1542 if (! re->id.named
1543 && re->id.u.id != (unsigned long) (unsigned int) *language
1544 && (re->id.u.id & 0xffff) == re->id.u.id)
1546 fprintf (e, "LANGUAGE %lu, %lu\n",
1547 re->id.u.id & ((1 << SUBLANG_SHIFT) - 1),
1548 (re->id.u.id >> SUBLANG_SHIFT) & 0xff);
1549 *language = re->id.u.id;
1551 break;
1553 default:
1554 break;
1557 if (re->subdir)
1558 write_rc_subdir (e, re, type, name, language, level);
1559 else
1561 if (level == 3)
1563 /* This is the normal case: the three levels are
1564 TYPE/NAME/LANGUAGE. NAME will have been set at level
1565 2, and represents the name to use. We probably just
1566 set LANGUAGE, and it will probably match what the
1567 resource itself records if anything. */
1568 write_rc_resource (e, type, name, re->u.res, language);
1570 else
1572 fprintf (e, "// Resource at unexpected level %d\n", level);
1573 write_rc_resource (e, type, (struct res_id *) NULL, re->u.res,
1574 language);
1580 /* Write out a subdirectory entry. E is the file to write to. RE is
1581 the subdirectory entry. TYPE and NAME are pointers to higher level
1582 IDs, or NULL. LANGUAGE is a pointer to the current language.
1583 LEVEL is the level in the tree. */
1585 static void
1586 write_rc_subdir (FILE *e, const struct res_entry *re,
1587 const struct res_id *type, const struct res_id *name,
1588 int *language, int level)
1590 fprintf (e, "\n");
1591 switch (level)
1593 case 1:
1594 fprintf (e, "// Type: ");
1595 if (re->id.named)
1596 res_id_print (e, re->id, 1);
1597 else
1599 const char *s;
1601 switch (re->id.u.id)
1603 case RT_CURSOR: s = "cursor"; break;
1604 case RT_BITMAP: s = "bitmap"; break;
1605 case RT_ICON: s = "icon"; break;
1606 case RT_MENU: s = "menu"; break;
1607 case RT_DIALOG: s = "dialog"; break;
1608 case RT_STRING: s = "stringtable"; break;
1609 case RT_FONTDIR: s = "fontdir"; break;
1610 case RT_FONT: s = "font"; break;
1611 case RT_ACCELERATOR: s = "accelerators"; break;
1612 case RT_RCDATA: s = "rcdata"; break;
1613 case RT_MESSAGETABLE: s = "messagetable"; break;
1614 case RT_GROUP_CURSOR: s = "group cursor"; break;
1615 case RT_GROUP_ICON: s = "group icon"; break;
1616 case RT_VERSION: s = "version"; break;
1617 case RT_DLGINCLUDE: s = "dlginclude"; break;
1618 case RT_PLUGPLAY: s = "plugplay"; break;
1619 case RT_VXD: s = "vxd"; break;
1620 case RT_ANICURSOR: s = "anicursor"; break;
1621 case RT_ANIICON: s = "aniicon"; break;
1622 default: s = NULL; break;
1625 if (s != NULL)
1626 fprintf (e, "%s", s);
1627 else
1628 res_id_print (e, re->id, 1);
1630 fprintf (e, "\n");
1631 break;
1633 case 2:
1634 fprintf (e, "// Name: ");
1635 res_id_print (e, re->id, 1);
1636 fprintf (e, "\n");
1637 break;
1639 case 3:
1640 fprintf (e, "// Language: ");
1641 res_id_print (e, re->id, 1);
1642 fprintf (e, "\n");
1643 break;
1645 default:
1646 fprintf (e, "// Level %d: ", level);
1647 res_id_print (e, re->id, 1);
1648 fprintf (e, "\n");
1651 write_rc_directory (e, re->u.dir, type, name, language, level + 1);
1654 /* Write out a single resource. E is the file to write to. TYPE is a
1655 pointer to the type of the resource. NAME is a pointer to the name
1656 of the resource; it will be NULL if there is a level mismatch. RES
1657 is the resource data. LANGUAGE is a pointer to the current
1658 language. */
1660 static void
1661 write_rc_resource (FILE *e, const struct res_id *type,
1662 const struct res_id *name, const struct res_resource *res,
1663 int *language)
1665 const char *s;
1666 int rt;
1667 int menuex = 0;
1669 fprintf (e, "\n");
1671 switch (res->type)
1673 default:
1674 abort ();
1676 case RES_TYPE_ACCELERATOR:
1677 s = "ACCELERATOR";
1678 rt = RT_ACCELERATOR;
1679 break;
1681 case RES_TYPE_BITMAP:
1682 s = "BITMAP";
1683 rt = RT_BITMAP;
1684 break;
1686 case RES_TYPE_CURSOR:
1687 s = "CURSOR";
1688 rt = RT_CURSOR;
1689 break;
1691 case RES_TYPE_GROUP_CURSOR:
1692 s = "GROUP_CURSOR";
1693 rt = RT_GROUP_CURSOR;
1694 break;
1696 case RES_TYPE_DIALOG:
1697 if (extended_dialog (res->u.dialog))
1698 s = "DIALOGEX";
1699 else
1700 s = "DIALOG";
1701 rt = RT_DIALOG;
1702 break;
1704 case RES_TYPE_FONT:
1705 s = "FONT";
1706 rt = RT_FONT;
1707 break;
1709 case RES_TYPE_FONTDIR:
1710 s = "FONTDIR";
1711 rt = RT_FONTDIR;
1712 break;
1714 case RES_TYPE_ICON:
1715 s = "ICON";
1716 rt = RT_ICON;
1717 break;
1719 case RES_TYPE_GROUP_ICON:
1720 s = "GROUP_ICON";
1721 rt = RT_GROUP_ICON;
1722 break;
1724 case RES_TYPE_MENU:
1725 if (extended_menu (res->u.menu))
1727 s = "MENUEX";
1728 menuex = 1;
1730 else
1732 s = "MENU";
1733 menuex = 0;
1735 rt = RT_MENU;
1736 break;
1738 case RES_TYPE_MESSAGETABLE:
1739 s = "MESSAGETABLE";
1740 rt = RT_MESSAGETABLE;
1741 break;
1743 case RES_TYPE_RCDATA:
1744 s = "RCDATA";
1745 rt = RT_RCDATA;
1746 break;
1748 case RES_TYPE_STRINGTABLE:
1749 s = "STRINGTABLE";
1750 rt = RT_STRING;
1751 break;
1753 case RES_TYPE_USERDATA:
1754 s = NULL;
1755 rt = 0;
1756 break;
1758 case RES_TYPE_VERSIONINFO:
1759 s = "VERSIONINFO";
1760 rt = RT_VERSION;
1761 break;
1764 if (rt != 0
1765 && type != NULL
1766 && (type->named || type->u.id != (unsigned long) rt))
1768 fprintf (e, "// Unexpected resource type mismatch: ");
1769 res_id_print (e, *type, 1);
1770 fprintf (e, " != %d", rt);
1773 if (res->coff_info.codepage != 0)
1774 fprintf (e, "// Code page: %lu\n", res->coff_info.codepage);
1775 if (res->coff_info.reserved != 0)
1776 fprintf (e, "// COFF reserved value: %lu\n", res->coff_info.reserved);
1778 if (name != NULL)
1779 res_id_print (e, *name, 0);
1780 else
1781 fprintf (e, "??Unknown-Name??");
1783 fprintf (e, " ");
1784 if (s != NULL)
1785 fprintf (e, "%s", s);
1786 else if (type != NULL)
1787 res_id_print (e, *type, 0);
1788 else
1789 fprintf (e, "??Unknown-Type??");
1791 if (res->res_info.memflags != 0)
1793 if ((res->res_info.memflags & MEMFLAG_MOVEABLE) != 0)
1794 fprintf (e, " MOVEABLE");
1795 if ((res->res_info.memflags & MEMFLAG_PURE) != 0)
1796 fprintf (e, " PURE");
1797 if ((res->res_info.memflags & MEMFLAG_PRELOAD) != 0)
1798 fprintf (e, " PRELOAD");
1799 if ((res->res_info.memflags & MEMFLAG_DISCARDABLE) != 0)
1800 fprintf (e, " DISCARDABLE");
1803 if (res->type == RES_TYPE_DIALOG)
1805 fprintf (e, " %d, %d, %d, %d", res->u.dialog->x, res->u.dialog->y,
1806 res->u.dialog->width, res->u.dialog->height);
1807 if (res->u.dialog->ex != NULL
1808 && res->u.dialog->ex->help != 0)
1809 fprintf (e, ", %lu", res->u.dialog->ex->help);
1812 fprintf (e, "\n");
1814 if ((res->res_info.language != 0 && res->res_info.language != *language)
1815 || res->res_info.characteristics != 0
1816 || res->res_info.version != 0)
1818 int modifiers;
1820 switch (res->type)
1822 case RES_TYPE_ACCELERATOR:
1823 case RES_TYPE_DIALOG:
1824 case RES_TYPE_MENU:
1825 case RES_TYPE_RCDATA:
1826 case RES_TYPE_STRINGTABLE:
1827 modifiers = 1;
1828 break;
1830 default:
1831 modifiers = 0;
1832 break;
1835 if (res->res_info.language != 0 && res->res_info.language != *language)
1836 fprintf (e, "%sLANGUAGE %d, %d\n",
1837 modifiers ? "// " : "",
1838 res->res_info.language & ((1<<SUBLANG_SHIFT)-1),
1839 (res->res_info.language >> SUBLANG_SHIFT) & 0xff);
1840 if (res->res_info.characteristics != 0)
1841 fprintf (e, "%sCHARACTERISTICS %lu\n",
1842 modifiers ? "// " : "",
1843 res->res_info.characteristics);
1844 if (res->res_info.version != 0)
1845 fprintf (e, "%sVERSION %lu\n",
1846 modifiers ? "// " : "",
1847 res->res_info.version);
1850 switch (res->type)
1852 default:
1853 abort ();
1855 case RES_TYPE_ACCELERATOR:
1856 write_rc_accelerators (e, res->u.acc);
1857 break;
1859 case RES_TYPE_CURSOR:
1860 write_rc_cursor (e, res->u.cursor);
1861 break;
1863 case RES_TYPE_GROUP_CURSOR:
1864 write_rc_group_cursor (e, res->u.group_cursor);
1865 break;
1867 case RES_TYPE_DIALOG:
1868 write_rc_dialog (e, res->u.dialog);
1869 break;
1871 case RES_TYPE_FONTDIR:
1872 write_rc_fontdir (e, res->u.fontdir);
1873 break;
1875 case RES_TYPE_GROUP_ICON:
1876 write_rc_group_icon (e, res->u.group_icon);
1877 break;
1879 case RES_TYPE_MENU:
1880 write_rc_menu (e, res->u.menu, menuex);
1881 break;
1883 case RES_TYPE_RCDATA:
1884 write_rc_rcdata (e, res->u.rcdata, 0);
1885 break;
1887 case RES_TYPE_STRINGTABLE:
1888 write_rc_stringtable (e, name, res->u.stringtable);
1889 break;
1891 case RES_TYPE_USERDATA:
1892 write_rc_rcdata (e, res->u.userdata, 0);
1893 break;
1895 case RES_TYPE_VERSIONINFO:
1896 write_rc_versioninfo (e, res->u.versioninfo);
1897 break;
1899 case RES_TYPE_BITMAP:
1900 case RES_TYPE_FONT:
1901 case RES_TYPE_ICON:
1902 case RES_TYPE_MESSAGETABLE:
1903 write_rc_filedata (e, res->u.data.length, res->u.data.data);
1904 break;
1908 /* Write out accelerator information. */
1910 static void
1911 write_rc_accelerators (FILE *e, const struct accelerator *accelerators)
1913 const struct accelerator *acc;
1915 fprintf (e, "BEGIN\n");
1916 for (acc = accelerators; acc != NULL; acc = acc->next)
1918 int printable;
1920 fprintf (e, " ");
1922 if ((acc->key & 0x7f) == acc->key
1923 && ISPRINT (acc->key)
1924 && (acc->flags & ACC_VIRTKEY) == 0)
1926 fprintf (e, "\"%c\"", acc->key);
1927 printable = 1;
1929 else
1931 fprintf (e, "%d", acc->key);
1932 printable = 0;
1935 fprintf (e, ", %d", acc->id);
1937 if (! printable)
1939 if ((acc->flags & ACC_VIRTKEY) != 0)
1940 fprintf (e, ", VIRTKEY");
1941 else
1942 fprintf (e, ", ASCII");
1945 if ((acc->flags & ACC_SHIFT) != 0)
1946 fprintf (e, ", SHIFT");
1947 if ((acc->flags & ACC_CONTROL) != 0)
1948 fprintf (e, ", CONTROL");
1949 if ((acc->flags & ACC_ALT) != 0)
1950 fprintf (e, ", ALT");
1952 fprintf (e, "\n");
1955 fprintf (e, "END\n");
1958 /* Write out cursor information. This would normally be in a separate
1959 file, which the rc file would include. */
1961 static void
1962 write_rc_cursor (FILE *e, const struct cursor *cursor)
1964 fprintf (e, "// Hotspot: x: %d; y: %d\n", cursor->xhotspot,
1965 cursor->yhotspot);
1966 write_rc_filedata (e, cursor->length, cursor->data);
1969 /* Write out group cursor data. This would normally be built from the
1970 cursor data. */
1972 static void
1973 write_rc_group_cursor (FILE *e, const struct group_cursor *group_cursor)
1975 const struct group_cursor *gc;
1977 for (gc = group_cursor; gc != NULL; gc = gc->next)
1979 fprintf (e, "// width: %d; height %d; planes %d; bits %d\n",
1980 gc->width, gc->height, gc->planes, gc->bits);
1981 fprintf (e, "// data bytes: %lu; index: %d\n",
1982 gc->bytes, gc->index);
1986 /* Write dialog data. */
1988 static void
1989 write_rc_dialog (FILE *e, const struct dialog *dialog)
1991 const struct dialog_control *control;
1993 fprintf (e, "STYLE 0x%lx\n", dialog->style);
1995 if (dialog->exstyle != 0)
1996 fprintf (e, "EXSTYLE 0x%lx\n", dialog->exstyle);
1998 if ((dialog->class.named && dialog->class.u.n.length > 0)
1999 || dialog->class.u.id != 0)
2001 fprintf (e, "CLASS ");
2002 res_id_print (e, dialog->class, 1);
2003 fprintf (e, "\n");
2006 if (dialog->caption != NULL)
2008 fprintf (e, "CAPTION \"");
2009 unicode_print (e, dialog->caption, -1);
2010 fprintf (e, "\"\n");
2013 if ((dialog->menu.named && dialog->menu.u.n.length > 0)
2014 || dialog->menu.u.id != 0)
2016 fprintf (e, "MENU ");
2017 res_id_print (e, dialog->menu, 0);
2018 fprintf (e, "\n");
2021 if (dialog->font != NULL)
2023 fprintf (e, "FONT %d, \"", dialog->pointsize);
2024 unicode_print (e, dialog->font, -1);
2025 fprintf (e, "\"");
2026 if (dialog->ex != NULL
2027 && (dialog->ex->weight != 0
2028 || dialog->ex->italic != 0
2029 || dialog->ex->charset != 1))
2030 fprintf (e, ", %d, %d, %d",
2031 dialog->ex->weight, dialog->ex->italic, dialog->ex->charset);
2032 fprintf (e, "\n");
2035 fprintf (e, "BEGIN\n");
2037 for (control = dialog->controls; control != NULL; control = control->next)
2038 write_rc_dialog_control (e, control);
2040 fprintf (e, "END\n");
2043 /* For each predefined control keyword, this table provides the class
2044 and the style. */
2046 struct control_info
2048 const char *name;
2049 unsigned short class;
2050 unsigned long style;
2053 static const struct control_info control_info[] =
2055 { "AUTO3STATE", CTL_BUTTON, BS_AUTO3STATE },
2056 { "AUTOCHECKBOX", CTL_BUTTON, BS_AUTOCHECKBOX },
2057 { "AUTORADIOBUTTON", CTL_BUTTON, BS_AUTORADIOBUTTON },
2058 { "CHECKBOX", CTL_BUTTON, BS_CHECKBOX },
2059 { "COMBOBOX", CTL_COMBOBOX, (unsigned long) -1 },
2060 { "CTEXT", CTL_STATIC, SS_CENTER },
2061 { "DEFPUSHBUTTON", CTL_BUTTON, BS_DEFPUSHBUTTON },
2062 { "EDITTEXT", CTL_EDIT, (unsigned long) -1 },
2063 { "GROUPBOX", CTL_BUTTON, BS_GROUPBOX },
2064 { "ICON", CTL_STATIC, SS_ICON },
2065 { "LISTBOX", CTL_LISTBOX, (unsigned long) -1 },
2066 { "LTEXT", CTL_STATIC, SS_LEFT },
2067 { "PUSHBOX", CTL_BUTTON, BS_PUSHBOX },
2068 { "PUSHBUTTON", CTL_BUTTON, BS_PUSHBUTTON },
2069 { "RADIOBUTTON", CTL_BUTTON, BS_RADIOBUTTON },
2070 { "RTEXT", CTL_STATIC, SS_RIGHT },
2071 { "SCROLLBAR", CTL_SCROLLBAR, (unsigned long) -1 },
2072 { "STATE3", CTL_BUTTON, BS_3STATE },
2073 /* It's important that USERBUTTON come after all the other button
2074 types, so that it won't be matched too early. */
2075 { "USERBUTTON", CTL_BUTTON, (unsigned long) -1 },
2076 { NULL, 0, 0 }
2079 /* Write a dialog control. */
2081 static void
2082 write_rc_dialog_control (FILE *e, const struct dialog_control *control)
2084 const struct control_info *ci;
2086 fprintf (e, " ");
2088 if (control->class.named)
2089 ci = NULL;
2090 else
2092 for (ci = control_info; ci->name != NULL; ++ci)
2093 if (ci->class == control->class.u.id
2094 && (ci->style == (unsigned long) -1
2095 || ci->style == (control->style & 0xff)))
2096 break;
2098 if (ci == NULL)
2099 fprintf (e, "CONTROL");
2100 else if (ci->name != NULL)
2101 fprintf (e, "%s", ci->name);
2102 else
2103 fprintf (e, "CONTROL");
2105 if (control->text.named || control->text.u.id != 0)
2107 fprintf (e, " ");
2108 res_id_print (e, control->text, 1);
2109 fprintf (e, ",");
2112 fprintf (e, " %d, ", control->id);
2114 if (ci == NULL)
2116 if (control->class.named)
2117 fprintf (e, "\"");
2118 res_id_print (e, control->class, 0);
2119 if (control->class.named)
2120 fprintf (e, "\"");
2121 fprintf (e, ", 0x%lx, ", control->style);
2124 fprintf (e, "%d, %d", control->x, control->y);
2126 if (control->style != SS_ICON
2127 || control->exstyle != 0
2128 || control->width != 0
2129 || control->height != 0
2130 || control->help != 0)
2132 fprintf (e, ", %d, %d", control->width, control->height);
2134 /* FIXME: We don't need to print the style if it is the default.
2135 More importantly, in certain cases we actually need to turn
2136 off parts of the forced style, by using NOT. */
2137 fprintf (e, ", 0x%lx", control->style);
2139 if (control->exstyle != 0 || control->help != 0)
2140 fprintf (e, ", 0x%lx, %lu", control->exstyle, control->help);
2143 fprintf (e, "\n");
2145 if (control->data != NULL)
2146 write_rc_rcdata (e, control->data, 2);
2149 /* Write out font directory data. This would normally be built from
2150 the font data. */
2152 static void
2153 write_rc_fontdir (FILE *e, const struct fontdir *fontdir)
2155 const struct fontdir *fc;
2157 for (fc = fontdir; fc != NULL; fc = fc->next)
2159 fprintf (e, "// Font index: %d\n", fc->index);
2160 write_rc_filedata (e, fc->length, fc->data);
2164 /* Write out group icon data. This would normally be built from the
2165 icon data. */
2167 static void
2168 write_rc_group_icon (FILE *e, const struct group_icon *group_icon)
2170 const struct group_icon *gi;
2172 for (gi = group_icon; gi != NULL; gi = gi->next)
2174 fprintf (e, "// width: %d; height %d; colors: %d; planes %d; bits %d\n",
2175 gi->width, gi->height, gi->colors, gi->planes, gi->bits);
2176 fprintf (e, "// data bytes: %lu; index: %d\n",
2177 gi->bytes, gi->index);
2181 /* Write out a menu resource. */
2183 static void
2184 write_rc_menu (FILE *e, const struct menu *menu, int menuex)
2186 if (menu->help != 0)
2187 fprintf (e, "// Help ID: %lu\n", menu->help);
2188 write_rc_menuitems (e, menu->items, menuex, 0);
2191 /* Write out menuitems. */
2193 static void
2194 write_rc_menuitems (FILE *e, const struct menuitem *menuitems, int menuex,
2195 int ind)
2197 const struct menuitem *mi;
2199 indent (e, ind);
2200 fprintf (e, "BEGIN\n");
2202 for (mi = menuitems; mi != NULL; mi = mi->next)
2204 indent (e, ind + 2);
2206 if (mi->popup == NULL)
2207 fprintf (e, "MENUITEM");
2208 else
2209 fprintf (e, "POPUP");
2211 if (! menuex
2212 && mi->popup == NULL
2213 && mi->text == NULL
2214 && mi->type == 0
2215 && mi->id == 0)
2217 fprintf (e, " SEPARATOR\n");
2218 continue;
2221 if (mi->text == NULL)
2222 fprintf (e, " \"\"");
2223 else
2225 fprintf (e, " \"");
2226 unicode_print (e, mi->text, -1);
2227 fprintf (e, "\"");
2230 if (! menuex)
2232 if (mi->popup == NULL)
2233 fprintf (e, ", %d", mi->id);
2235 if ((mi->type & MENUITEM_CHECKED) != 0)
2236 fprintf (e, ", CHECKED");
2237 if ((mi->type & MENUITEM_GRAYED) != 0)
2238 fprintf (e, ", GRAYED");
2239 if ((mi->type & MENUITEM_HELP) != 0)
2240 fprintf (e, ", HELP");
2241 if ((mi->type & MENUITEM_INACTIVE) != 0)
2242 fprintf (e, ", INACTIVE");
2243 if ((mi->type & MENUITEM_MENUBARBREAK) != 0)
2244 fprintf (e, ", MENUBARBREAK");
2245 if ((mi->type & MENUITEM_MENUBREAK) != 0)
2246 fprintf (e, ", MENUBREAK");
2248 else
2250 if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0)
2252 fprintf (e, ", %d", mi->id);
2253 if (mi->type != 0 || mi->state != 0 || mi->help != 0)
2255 fprintf (e, ", %lu", mi->type);
2256 if (mi->state != 0 || mi->help != 0)
2258 fprintf (e, ", %lu", mi->state);
2259 if (mi->help != 0)
2260 fprintf (e, ", %lu", mi->help);
2266 fprintf (e, "\n");
2268 if (mi->popup != NULL)
2269 write_rc_menuitems (e, mi->popup, menuex, ind + 2);
2272 indent (e, ind);
2273 fprintf (e, "END\n");
2276 /* Write out an rcdata resource. This is also used for other types of
2277 resources that need to print arbitrary data. */
2279 static void
2280 write_rc_rcdata (FILE *e, const struct rcdata_item *rcdata, int ind)
2282 const struct rcdata_item *ri;
2284 indent (e, ind);
2285 fprintf (e, "BEGIN\n");
2287 for (ri = rcdata; ri != NULL; ri = ri->next)
2289 if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0)
2290 continue;
2292 indent (e, ind + 2);
2294 switch (ri->type)
2296 default:
2297 abort ();
2299 case RCDATA_WORD:
2300 fprintf (e, "%d", ri->u.word);
2301 break;
2303 case RCDATA_DWORD:
2304 fprintf (e, "%luL", ri->u.dword);
2305 break;
2307 case RCDATA_STRING:
2309 const char *s;
2310 unsigned long i;
2312 fprintf (e, "\"");
2313 s = ri->u.string.s;
2314 for (i = 0; i < ri->u.string.length; i++)
2316 if (ISPRINT (*s))
2317 putc (*s, e);
2318 else
2319 fprintf (e, "\\%03o", *s);
2321 fprintf (e, "\"");
2322 break;
2325 case RCDATA_WSTRING:
2326 fprintf (e, "L\"");
2327 unicode_print (e, ri->u.wstring.w, ri->u.wstring.length);
2328 fprintf (e, "\"");
2329 break;
2331 case RCDATA_BUFFER:
2333 unsigned long i;
2334 int first;
2336 /* Assume little endian data. */
2338 first = 1;
2339 for (i = 0; i + 3 < ri->u.buffer.length; i += 4)
2341 unsigned long l;
2342 int j;
2344 if (! first)
2345 indent (e, ind + 2);
2346 l = ((((((ri->u.buffer.data[i + 3] << 8)
2347 | ri->u.buffer.data[i + 2]) << 8)
2348 | ri->u.buffer.data[i + 1]) << 8)
2349 | ri->u.buffer.data[i]);
2350 fprintf (e, "%luL", l);
2351 if (i + 4 < ri->u.buffer.length || ri->next != NULL)
2352 fprintf (e, ",");
2353 for (j = 0; j < 4; ++j)
2354 if (! ISPRINT (ri->u.buffer.data[i + j])
2355 && ri->u.buffer.data[i + j] != 0)
2356 break;
2357 if (j >= 4)
2359 fprintf (e, "\t// ");
2360 for (j = 0; j < 4; ++j)
2362 if (! ISPRINT (ri->u.buffer.data[i + j]))
2363 fprintf (e, "\\%03o", ri->u.buffer.data[i + j]);
2364 else
2366 if (ri->u.buffer.data[i + j] == '\\')
2367 fprintf (e, "\\");
2368 fprintf (e, "%c", ri->u.buffer.data[i + j]);
2372 fprintf (e, "\n");
2373 first = 0;
2376 if (i + 1 < ri->u.buffer.length)
2378 int s;
2379 int j;
2381 if (! first)
2382 indent (e, ind + 2);
2383 s = (ri->u.buffer.data[i + 1] << 8) | ri->u.buffer.data[i];
2384 fprintf (e, "%d", s);
2385 if (i + 2 < ri->u.buffer.length || ri->next != NULL)
2386 fprintf (e, ",");
2387 for (j = 0; j < 2; ++j)
2388 if (! ISPRINT (ri->u.buffer.data[i + j])
2389 && ri->u.buffer.data[i + j] != 0)
2390 break;
2391 if (j >= 2)
2393 fprintf (e, "\t// ");
2394 for (j = 0; j < 2; ++j)
2396 if (! ISPRINT (ri->u.buffer.data[i + j]))
2397 fprintf (e, "\\%03o", ri->u.buffer.data[i + j]);
2398 else
2400 if (ri->u.buffer.data[i + j] == '\\')
2401 fprintf (e, "\\");
2402 fprintf (e, "%c", ri->u.buffer.data[i + j]);
2406 fprintf (e, "\n");
2407 i += 2;
2408 first = 0;
2411 if (i < ri->u.buffer.length)
2413 if (! first)
2414 indent (e, ind + 2);
2415 if ((ri->u.buffer.data[i] & 0x7f) == ri->u.buffer.data[i]
2416 && ISPRINT (ri->u.buffer.data[i]))
2417 fprintf (e, "\"%c\"", ri->u.buffer.data[i]);
2418 else
2419 fprintf (e, "\"\\%03o\"", ri->u.buffer.data[i]);
2420 if (ri->next != NULL)
2421 fprintf (e, ",");
2422 fprintf (e, "\n");
2423 first = 0;
2426 break;
2430 if (ri->type != RCDATA_BUFFER)
2432 if (ri->next != NULL)
2433 fprintf (e, ",");
2434 fprintf (e, "\n");
2438 indent (e, ind);
2439 fprintf (e, "END\n");
2442 /* Write out a stringtable resource. */
2444 static void
2445 write_rc_stringtable (FILE *e, const struct res_id *name,
2446 const struct stringtable *stringtable)
2448 unsigned long offset;
2449 int i;
2451 if (name != NULL && ! name->named)
2452 offset = (name->u.id - 1) << 4;
2453 else
2455 fprintf (e, "// %s string table name\n",
2456 name == NULL ? "Missing" : "Invalid");
2457 offset = 0;
2460 fprintf (e, "BEGIN\n");
2462 for (i = 0; i < 16; i++)
2464 if (stringtable->strings[i].length != 0)
2466 fprintf (e, " %lu, \"", offset + i);
2467 unicode_print (e, stringtable->strings[i].string,
2468 stringtable->strings[i].length);
2469 fprintf (e, "\"\n");
2473 fprintf (e, "END\n");
2476 /* Write out a versioninfo resource. */
2478 static void
2479 write_rc_versioninfo (FILE *e, const struct versioninfo *versioninfo)
2481 const struct fixed_versioninfo *f;
2482 const struct ver_info *vi;
2484 f = versioninfo->fixed;
2485 if (f->file_version_ms != 0 || f->file_version_ls != 0)
2486 fprintf (e, " FILEVERSION %lu, %lu, %lu, %lu\n",
2487 (f->file_version_ms >> 16) & 0xffff,
2488 f->file_version_ms & 0xffff,
2489 (f->file_version_ls >> 16) & 0xffff,
2490 f->file_version_ls & 0xffff);
2491 if (f->product_version_ms != 0 || f->product_version_ls != 0)
2492 fprintf (e, " PRODUCTVERSION %lu, %lu, %lu, %lu\n",
2493 (f->product_version_ms >> 16) & 0xffff,
2494 f->product_version_ms & 0xffff,
2495 (f->product_version_ls >> 16) & 0xffff,
2496 f->product_version_ls & 0xffff);
2497 if (f->file_flags_mask != 0)
2498 fprintf (e, " FILEFLAGSMASK 0x%lx\n", f->file_flags_mask);
2499 if (f->file_flags != 0)
2500 fprintf (e, " FILEFLAGS 0x%lx\n", f->file_flags);
2501 if (f->file_os != 0)
2502 fprintf (e, " FILEOS 0x%lx\n", f->file_os);
2503 if (f->file_type != 0)
2504 fprintf (e, " FILETYPE 0x%lx\n", f->file_type);
2505 if (f->file_subtype != 0)
2506 fprintf (e, " FILESUBTYPE 0x%lx\n", f->file_subtype);
2507 if (f->file_date_ms != 0 || f->file_date_ls != 0)
2508 fprintf (e, "// Date: %lu, %lu\n", f->file_date_ms, f->file_date_ls);
2510 fprintf (e, "BEGIN\n");
2512 for (vi = versioninfo->var; vi != NULL; vi = vi->next)
2514 switch (vi->type)
2516 case VERINFO_STRING:
2518 const struct ver_stringinfo *vs;
2520 fprintf (e, " BLOCK \"StringFileInfo\"\n");
2521 fprintf (e, " BEGIN\n");
2522 fprintf (e, " BLOCK \"");
2523 unicode_print (e, vi->u.string.language, -1);
2524 fprintf (e, "\"\n");
2525 fprintf (e, " BEGIN\n");
2527 for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
2529 fprintf (e, " VALUE \"");
2530 unicode_print (e, vs->key, -1);
2531 fprintf (e, "\", \"");
2532 unicode_print (e, vs->value, -1);
2533 fprintf (e, "\"\n");
2536 fprintf (e, " END\n");
2537 fprintf (e, " END\n");
2538 break;
2541 case VERINFO_VAR:
2543 const struct ver_varinfo *vv;
2545 fprintf (e, " BLOCK \"VarFileInfo\"\n");
2546 fprintf (e, " BEGIN\n");
2547 fprintf (e, " VALUE \"");
2548 unicode_print (e, vi->u.var.key, -1);
2549 fprintf (e, "\"");
2551 for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
2552 fprintf (e, ", 0x%x, %d", (unsigned int) vv->language,
2553 vv->charset);
2555 fprintf (e, "\n END\n");
2557 break;
2562 fprintf (e, "END\n");
2565 /* Write out data which would normally be read from a file. */
2567 static void
2568 write_rc_filedata (FILE *e, unsigned long length, const unsigned char *data)
2570 unsigned long i;
2572 for (i = 0; i + 15 < length; i += 16)
2574 fprintf (e, "// %4lx: ", i);
2575 fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x ",
2576 data[i + 0], data[i + 1], data[i + 2], data[i + 3],
2577 data[i + 4], data[i + 5], data[i + 6], data[i + 7]);
2578 fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
2579 data[i + 8], data[i + 9], data[i + 10], data[i + 11],
2580 data[i + 12], data[i + 13], data[i + 14], data[i + 15]);
2583 if (i < length)
2585 fprintf (e, "// %4lx:", i);
2586 while (i < length)
2588 fprintf (e, " %02x", data[i]);
2589 ++i;
2591 fprintf (e, "\n");