ATMEL AVR microcontroller support.
[binutils.git] / binutils / resrc.c
blob8c3c9a74d2241eb766754fdb7f55f6116be8ab07
1 /* resrc.c -- read and write Windows rc files.
2 Copyright 1997, 1998, 1999 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor, Cygnus Support.
5 This file is part of GNU Binutils.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
22 /* This file contains functions that read and write Windows rc files.
23 These are text files that represent resources. */
25 #include "bfd.h"
26 #include "bucomm.h"
27 #include "libiberty.h"
28 #include "windres.h"
30 #include <assert.h>
31 #include <ctype.h>
32 #include <errno.h>
33 #include <sys/stat.h>
34 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
38 #ifdef HAVE_SYS_WAIT_H
39 #include <sys/wait.h>
40 #else /* ! HAVE_SYS_WAIT_H */
41 #if ! defined (_WIN32) || defined (__CYGWIN__)
42 #ifndef WIFEXITED
43 #define WIFEXITED(w) (((w)&0377) == 0)
44 #endif
45 #ifndef WIFSIGNALED
46 #define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
47 #endif
48 #ifndef WTERMSIG
49 #define WTERMSIG(w) ((w) & 0177)
50 #endif
51 #ifndef WEXITSTATUS
52 #define WEXITSTATUS(w) (((w) >> 8) & 0377)
53 #endif
54 #else /* defined (_WIN32) && ! defined (__CYGWIN__) */
55 #ifndef WIFEXITED
56 #define WIFEXITED(w) (((w) & 0xff) == 0)
57 #endif
58 #ifndef WIFSIGNALED
59 #define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
60 #endif
61 #ifndef WTERMSIG
62 #define WTERMSIG(w) ((w) & 0x7f)
63 #endif
64 #ifndef WEXITSTATUS
65 #define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
66 #endif
67 #endif /* defined (_WIN32) && ! defined (__CYGWIN__) */
68 #endif /* ! HAVE_SYS_WAIT_H */
70 #ifndef STDOUT_FILENO
71 #define STDOUT_FILENO 1
72 #endif
74 #if defined (_WIN32) && ! defined (__CYGWIN__)
75 #define popen _popen
76 #define pclose _pclose
77 #endif
79 /* The default preprocessor. */
81 #define DEFAULT_PREPROCESSOR "gcc -E -xc-header -DRC_INVOKED"
83 /* We read the directory entries in a cursor or icon file into
84 instances of this structure. */
86 struct icondir
88 /* Width of image. */
89 unsigned char width;
90 /* Height of image. */
91 unsigned char height;
92 /* Number of colors in image. */
93 unsigned char colorcount;
94 union
96 struct
98 /* Color planes. */
99 unsigned short planes;
100 /* Bits per pixel. */
101 unsigned short bits;
102 } icon;
103 struct
105 /* X coordinate of hotspot. */
106 unsigned short xhotspot;
107 /* Y coordinate of hotspot. */
108 unsigned short yhotspot;
109 } cursor;
110 } u;
111 /* Bytes in image. */
112 unsigned long bytes;
113 /* File offset of image. */
114 unsigned long offset;
117 /* The name of the rc file we are reading. */
119 char *rc_filename;
121 /* The line number in the rc file. */
123 int rc_lineno;
125 /* The pipe we are reading from, so that we can close it if we exit. */
127 static FILE *cpp_pipe;
129 /* The temporary file used if we're not using popen, so we can delete it
130 if we exit. */
132 static char *cpp_temp_file;
134 /* Input stream is either a file or a pipe. */
136 static enum {ISTREAM_PIPE, ISTREAM_FILE} istream_type;
138 /* As we read the rc file, we attach information to this structure. */
140 static struct res_directory *resources;
142 /* The number of cursor resources we have written out. */
144 static int cursors;
146 /* The number of font resources we have written out. */
148 static int fonts;
150 /* Font directory information. */
152 struct fontdir *fontdirs;
154 /* Resource info to use for fontdirs. */
156 struct res_res_info fontdirs_resinfo;
158 /* The number of icon resources we have written out. */
160 static int icons;
162 /* Local functions. */
164 static int run_cmd PARAMS ((char *, const char *));
165 static FILE *open_input_stream PARAMS ((char *));
166 static FILE *look_for_default PARAMS ((char *, const char *, int,
167 const char *, const char *));
168 static void close_input_stream PARAMS ((void));
169 static void unexpected_eof PARAMS ((const char *));
170 static int get_word PARAMS ((FILE *, const char *));
171 static unsigned long get_long PARAMS ((FILE *, const char *));
172 static void get_data
173 PARAMS ((FILE *, unsigned char *, unsigned long, const char *));
174 static void define_fontdirs PARAMS ((void));
176 /* Run `cmd' and redirect the output to `redir'. */
178 static int
179 run_cmd (cmd, redir)
180 char *cmd;
181 const char *redir;
183 char *s;
184 int pid, wait_status, retcode;
185 int i;
186 const char **argv;
187 char *errmsg_fmt, *errmsg_arg;
188 char *temp_base = choose_temp_base ();
189 int in_quote;
190 char sep;
191 int redir_handle = -1;
192 int stdout_save = -1;
194 /* Count the args. */
195 i = 0;
197 for (s = cmd; *s; s++)
198 if (*s == ' ')
199 i++;
201 i++;
202 argv = alloca (sizeof (char *) * (i + 3));
203 i = 0;
204 s = cmd;
206 while (1)
208 while (*s == ' ' && *s != 0)
209 s++;
211 if (*s == 0)
212 break;
214 in_quote = (*s == '\'' || *s == '"');
215 sep = (in_quote) ? *s++ : ' ';
216 argv[i++] = s;
218 while (*s != sep && *s != 0)
219 s++;
221 if (*s == 0)
222 break;
224 *s++ = 0;
226 if (in_quote)
227 s++;
229 argv[i++] = NULL;
231 /* Setup the redirection. We can't use the usual fork/exec and redirect
232 since we may be running on non-POSIX Windows host. */
234 fflush (stdout);
235 fflush (stderr);
237 /* Open temporary output file. */
238 redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT, 0666);
239 if (redir_handle == -1)
240 fatal (_("can't open temporary file `%s': %s"), redir,
241 strerror (errno));
243 /* Duplicate the stdout file handle so it can be restored later. */
244 stdout_save = dup (STDOUT_FILENO);
245 if (stdout_save == -1)
246 fatal (_("can't redirect stdout: `%s': %s"), redir, strerror (errno));
248 /* Redirect stdout to our output file. */
249 dup2 (redir_handle, STDOUT_FILENO);
251 pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
252 &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
254 /* Restore stdout to its previous setting. */
255 dup2 (stdout_save, STDOUT_FILENO);
257 /* Close reponse file. */
258 close (redir_handle);
260 if (pid == -1)
262 fatal (_("%s %s: %s"), errmsg_fmt, errmsg_arg, strerror (errno));
263 return 1;
266 retcode = 0;
267 pid = pwait (pid, &wait_status, 0);
269 if (pid == -1)
271 fatal (_("wait: %s"), strerror (errno));
272 retcode = 1;
274 else if (WIFSIGNALED (wait_status))
276 fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
277 retcode = 1;
279 else if (WIFEXITED (wait_status))
281 if (WEXITSTATUS (wait_status) != 0)
283 fatal (_("%s exited with status %d"), cmd,
284 WEXITSTATUS (wait_status));
285 retcode = 1;
288 else
289 retcode = 1;
291 return retcode;
294 static FILE *
295 open_input_stream (cmd)
296 char *cmd;
298 if (istream_type == ISTREAM_FILE)
300 char *fileprefix;
302 fileprefix = choose_temp_base ();
303 cpp_temp_file = (char *) xmalloc (strlen (fileprefix) + 5);
304 sprintf (cpp_temp_file, "%s.irc", fileprefix);
305 free (fileprefix);
307 if (run_cmd (cmd, cpp_temp_file))
308 fatal (_("can't execute `%s': %s"), cmd, strerror (errno));
310 cpp_pipe = fopen (cpp_temp_file, FOPEN_RT);;
311 if (cpp_pipe == NULL)
312 fatal (_("can't open temporary file `%s': %s"),
313 cpp_temp_file, strerror (errno));
315 if (verbose)
316 fprintf (stderr,
317 _("Using temporary file `%s' to read preprocessor output\n"),
318 cpp_temp_file);
320 else
322 cpp_pipe = popen (cmd, FOPEN_RT);
323 if (cpp_pipe == NULL)
324 fatal (_("can't popen `%s': %s"), cmd, strerror (errno));
325 if (verbose)
326 fprintf (stderr, _("Using popen to read preprocessor output\n"));
329 xatexit (close_input_stream);
330 return cpp_pipe;
333 /* look for the preprocessor program */
335 static FILE *
336 look_for_default (cmd, prefix, end_prefix, preprocargs, filename)
337 char *cmd;
338 const char *prefix;
339 int end_prefix;
340 const char *preprocargs;
341 const char *filename;
343 char *space;
344 int found;
345 struct stat s;
347 strcpy (cmd, prefix);
349 sprintf (cmd + end_prefix, "%s", DEFAULT_PREPROCESSOR);
350 space = strchr (cmd + end_prefix, ' ');
351 if (space)
352 *space = 0;
354 if (
355 #if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32)
356 strchr (cmd, '\\') ||
357 #endif
358 strchr (cmd, '/'))
360 found = (stat (cmd, &s) == 0
361 #ifdef HAVE_EXECUTABLE_SUFFIX
362 || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
363 #endif
366 if (! found)
368 if (verbose)
369 fprintf (stderr, _("Tried `%s'\n"), cmd);
370 return NULL;
374 strcpy (cmd, prefix);
376 sprintf (cmd + end_prefix, "%s %s %s",
377 DEFAULT_PREPROCESSOR, preprocargs, filename);
379 if (verbose)
380 fprintf (stderr, _("Using `%s'\n"), cmd);
382 cpp_pipe = open_input_stream (cmd);
383 return cpp_pipe;
386 /* Read an rc file. */
388 struct res_directory *
389 read_rc_file (filename, preprocessor, preprocargs, language, use_temp_file)
390 const char *filename;
391 const char *preprocessor;
392 const char *preprocargs;
393 int language;
394 int use_temp_file;
396 char *cmd;
398 istream_type = (use_temp_file) ? ISTREAM_FILE : ISTREAM_PIPE;
400 if (preprocargs == NULL)
401 preprocargs = "";
402 if (filename == NULL)
403 filename = "-";
405 if (preprocessor)
407 cmd = xmalloc (strlen (preprocessor)
408 + strlen (preprocargs)
409 + strlen (filename)
410 + 10);
411 sprintf (cmd, "%s %s %s", preprocessor, preprocargs, filename);
413 cpp_pipe = open_input_stream (cmd);
415 else
417 char *dash, *slash, *cp;
419 preprocessor = DEFAULT_PREPROCESSOR;
421 cmd = xmalloc (strlen (program_name)
422 + strlen (preprocessor)
423 + strlen (preprocargs)
424 + strlen (filename)
425 #ifdef HAVE_EXECUTABLE_SUFFIX
426 + strlen (EXECUTABLE_SUFFIX)
427 #endif
428 + 10);
431 dash = slash = 0;
432 for (cp = program_name; *cp; cp++)
434 if (*cp == '-')
435 dash = cp;
436 if (
437 #if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32)
438 *cp == ':' || *cp == '\\' ||
439 #endif
440 *cp == '/')
442 slash = cp;
443 dash = 0;
447 cpp_pipe = 0;
449 if (dash)
451 /* First, try looking for a prefixed gcc in the windres
452 directory, with the same prefix as windres */
454 cpp_pipe = look_for_default (cmd, program_name, dash-program_name+1,
455 preprocargs, filename);
458 if (slash && !cpp_pipe)
460 /* Next, try looking for a gcc in the same directory as
461 that windres */
463 cpp_pipe = look_for_default (cmd, program_name, slash-program_name+1,
464 preprocargs, filename);
467 if (!cpp_pipe)
469 /* Sigh, try the default */
471 cpp_pipe = look_for_default (cmd, "", 0, preprocargs, filename);
476 free (cmd);
478 rc_filename = xstrdup (filename);
479 rc_lineno = 1;
480 if (language != -1)
481 rcparse_set_language (language);
482 yyin = cpp_pipe;
483 yyparse ();
485 close_input_stream ();
487 if (fontdirs != NULL)
488 define_fontdirs ();
490 free (rc_filename);
491 rc_filename = NULL;
493 return resources;
496 /* Close the input stream if it is open. */
498 static void
499 close_input_stream ()
501 if (cpp_pipe != NULL)
502 pclose (cpp_pipe);
504 if (istream_type == ISTREAM_FILE)
506 if (cpp_pipe != NULL)
507 fclose (cpp_pipe);
509 if (cpp_temp_file != NULL)
511 int errno_save = errno;
513 unlink (cpp_temp_file);
514 errno = errno_save;
515 free (cpp_temp_file);
518 else
520 if (cpp_pipe != NULL)
521 pclose (cpp_pipe);
524 /* Since this is also run via xatexit, safeguard. */
525 cpp_pipe = NULL;
526 cpp_temp_file = NULL;
529 /* Report an error while reading an rc file. */
531 void
532 yyerror (msg)
533 const char *msg;
535 fatal ("%s:%d: %s", rc_filename, rc_lineno, msg);
538 /* Issue a warning while reading an rc file. */
540 void
541 rcparse_warning (msg)
542 const char *msg;
544 fprintf (stderr, _("%s:%d: %s\n"), rc_filename, rc_lineno, msg);
547 /* Die if we get an unexpected end of file. */
549 static void
550 unexpected_eof (msg)
551 const char *msg;
553 fatal (_("%s: unexpected EOF"), msg);
556 /* Read a 16 bit word from a file. The data is assumed to be little
557 endian. */
559 static int
560 get_word (e, msg)
561 FILE *e;
562 const char *msg;
564 int b1, b2;
566 b1 = getc (e);
567 b2 = getc (e);
568 if (feof (e))
569 unexpected_eof (msg);
570 return ((b2 & 0xff) << 8) | (b1 & 0xff);
573 /* Read a 32 bit word from a file. The data is assumed to be little
574 endian. */
576 static unsigned long
577 get_long (e, msg)
578 FILE *e;
579 const char *msg;
581 int b1, b2, b3, b4;
583 b1 = getc (e);
584 b2 = getc (e);
585 b3 = getc (e);
586 b4 = getc (e);
587 if (feof (e))
588 unexpected_eof (msg);
589 return (((((((b4 & 0xff) << 8)
590 | (b3 & 0xff)) << 8)
591 | (b2 & 0xff)) << 8)
592 | (b1 & 0xff));
595 /* Read data from a file. This is a wrapper to do error checking. */
597 static void
598 get_data (e, p, c, msg)
599 FILE *e;
600 unsigned char *p;
601 unsigned long c;
602 const char *msg;
604 unsigned long got;
606 got = fread (p, 1, c, e);
607 if (got == c)
608 return;
610 fatal (_("%s: read of %lu returned %lu"), msg, c, got);
613 /* Define an accelerator resource. */
615 void
616 define_accelerator (id, resinfo, data)
617 struct res_id id;
618 const struct res_res_info *resinfo;
619 struct accelerator *data;
621 struct res_resource *r;
623 r = define_standard_resource (&resources, RT_ACCELERATOR, id,
624 resinfo->language, 0);
625 r->type = RES_TYPE_ACCELERATOR;
626 r->u.acc = data;
627 r->res_info = *resinfo;
630 /* Define a bitmap resource. Bitmap data is stored in a file. The
631 first 14 bytes of the file are a standard header, which is not
632 included in the resource data. */
634 #define BITMAP_SKIP (14)
636 void
637 define_bitmap (id, resinfo, filename)
638 struct res_id id;
639 const struct res_res_info *resinfo;
640 const char *filename;
642 FILE *e;
643 char *real_filename;
644 struct stat s;
645 unsigned char *data;
646 int i;
647 struct res_resource *r;
649 e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename);
651 if (stat (real_filename, &s) < 0)
652 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
653 strerror (errno));
655 data = (unsigned char *) res_alloc (s.st_size - BITMAP_SKIP);
657 for (i = 0; i < BITMAP_SKIP; i++)
658 getc (e);
660 get_data (e, data, s.st_size - BITMAP_SKIP, real_filename);
662 fclose (e);
663 free (real_filename);
665 r = define_standard_resource (&resources, RT_BITMAP, id,
666 resinfo->language, 0);
668 r->type = RES_TYPE_BITMAP;
669 r->u.data.length = s.st_size - BITMAP_SKIP;
670 r->u.data.data = data;
671 r->res_info = *resinfo;
674 /* Define a cursor resource. A cursor file may contain a set of
675 bitmaps, each representing the same cursor at various different
676 resolutions. They each get written out with a different ID. The
677 real cursor resource is then a group resource which can be used to
678 select one of the actual cursors. */
680 void
681 define_cursor (id, resinfo, filename)
682 struct res_id id;
683 const struct res_res_info *resinfo;
684 const char *filename;
686 FILE *e;
687 char *real_filename;
688 int type, count, i;
689 struct icondir *icondirs;
690 int first_cursor;
691 struct res_resource *r;
692 struct group_cursor *first, **pp;
694 e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename);
696 /* A cursor file is basically an icon file. The start of the file
697 is a three word structure. The first word is ignored. The
698 second word is the type of data. The third word is the number of
699 entries. */
701 get_word (e, real_filename);
702 type = get_word (e, real_filename);
703 count = get_word (e, real_filename);
704 if (type != 2)
705 fatal (_("cursor file `%s' does not contain cursor data"), real_filename);
707 /* Read in the icon directory entries. */
709 icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
711 for (i = 0; i < count; i++)
713 icondirs[i].width = getc (e);
714 icondirs[i].height = getc (e);
715 icondirs[i].colorcount = getc (e);
716 getc (e);
717 icondirs[i].u.cursor.xhotspot = get_word (e, real_filename);
718 icondirs[i].u.cursor.yhotspot = get_word (e, real_filename);
719 icondirs[i].bytes = get_long (e, real_filename);
720 icondirs[i].offset = get_long (e, real_filename);
722 if (feof (e))
723 unexpected_eof (real_filename);
726 /* Define each cursor as a unique resource. */
728 first_cursor = cursors;
730 for (i = 0; i < count; i++)
732 unsigned char *data;
733 struct res_id name;
734 struct cursor *c;
736 if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
737 fatal (_("%s: fseek to %lu failed: %s"), real_filename,
738 icondirs[i].offset, strerror (errno));
740 data = (unsigned char *) res_alloc (icondirs[i].bytes);
742 get_data (e, data, icondirs[i].bytes, real_filename);
744 c = (struct cursor *) res_alloc (sizeof *c);
745 c->xhotspot = icondirs[i].u.cursor.xhotspot;
746 c->yhotspot = icondirs[i].u.cursor.yhotspot;
747 c->length = icondirs[i].bytes;
748 c->data = data;
750 ++cursors;
752 name.named = 0;
753 name.u.id = cursors;
755 r = define_standard_resource (&resources, RT_CURSOR, name,
756 resinfo->language, 0);
757 r->type = RES_TYPE_CURSOR;
758 r->u.cursor = c;
759 r->res_info = *resinfo;
762 fclose (e);
763 free (real_filename);
765 /* Define a cursor group resource. */
767 first = NULL;
768 pp = &first;
769 for (i = 0; i < count; i++)
771 struct group_cursor *cg;
773 cg = (struct group_cursor *) res_alloc (sizeof *cg);
774 cg->next = NULL;
775 cg->width = icondirs[i].width;
776 cg->height = 2 * icondirs[i].height;
778 /* FIXME: What should these be set to? */
779 cg->planes = 1;
780 cg->bits = 1;
782 cg->bytes = icondirs[i].bytes + 4;
783 cg->index = first_cursor + i + 1;
785 *pp = cg;
786 pp = &(*pp)->next;
789 free (icondirs);
791 r = define_standard_resource (&resources, RT_GROUP_CURSOR, id,
792 resinfo->language, 0);
793 r->type = RES_TYPE_GROUP_CURSOR;
794 r->u.group_cursor = first;
795 r->res_info = *resinfo;
798 /* Define a dialog resource. */
800 void
801 define_dialog (id, resinfo, dialog)
802 struct res_id id;
803 const struct res_res_info *resinfo;
804 const struct dialog *dialog;
806 struct dialog *copy;
807 struct res_resource *r;
809 copy = (struct dialog *) res_alloc (sizeof *copy);
810 *copy = *dialog;
812 r = define_standard_resource (&resources, RT_DIALOG, id,
813 resinfo->language, 0);
814 r->type = RES_TYPE_DIALOG;
815 r->u.dialog = copy;
816 r->res_info = *resinfo;
819 /* Define a dialog control. This does not define a resource, but
820 merely allocates and fills in a structure. */
822 struct dialog_control *
823 define_control (text, id, x, y, width, height, class, style, exstyle)
824 const char *text;
825 unsigned long id;
826 unsigned long x;
827 unsigned long y;
828 unsigned long width;
829 unsigned long height;
830 unsigned long class;
831 unsigned long style;
832 unsigned long exstyle;
834 struct dialog_control *n;
836 n = (struct dialog_control *) res_alloc (sizeof *n);
837 n->next = NULL;
838 n->id = id;
839 n->style = style;
840 n->exstyle = exstyle;
841 n->x = x;
842 n->y = y;
843 n->width = width;
844 n->height = height;
845 n->class.named = 0;
846 n->class.u.id = class;
847 if (text != NULL)
848 res_string_to_id (&n->text, text);
849 else
851 n->text.named = 0;
852 n->text.u.id = 0;
854 n->data = NULL;
855 n->help = 0;
857 return n;
860 /* Define a font resource. */
862 void
863 define_font (id, resinfo, filename)
864 struct res_id id;
865 const struct res_res_info *resinfo;
866 const char *filename;
868 FILE *e;
869 char *real_filename;
870 struct stat s;
871 unsigned char *data;
872 struct res_resource *r;
873 long offset;
874 long fontdatalength;
875 unsigned char *fontdata;
876 struct fontdir *fd;
877 const char *device, *face;
878 struct fontdir **pp;
880 e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
882 if (stat (real_filename, &s) < 0)
883 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
884 strerror (errno));
886 data = (unsigned char *) res_alloc (s.st_size);
888 get_data (e, data, s.st_size, real_filename);
890 fclose (e);
891 free (real_filename);
893 r = define_standard_resource (&resources, RT_FONT, id,
894 resinfo->language, 0);
896 r->type = RES_TYPE_FONT;
897 r->u.data.length = s.st_size;
898 r->u.data.data = data;
899 r->res_info = *resinfo;
901 /* For each font resource, we must add an entry in the FONTDIR
902 resource. The FONTDIR resource includes some strings in the font
903 file. To find them, we have to do some magic on the data we have
904 read. */
906 offset = ((((((data[47] << 8)
907 | data[46]) << 8)
908 | data[45]) << 8)
909 | data[44]);
910 if (offset > 0 && offset < s.st_size)
911 device = (char *) data + offset;
912 else
913 device = "";
915 offset = ((((((data[51] << 8)
916 | data[50]) << 8)
917 | data[49]) << 8)
918 | data[48]);
919 if (offset > 0 && offset < s.st_size)
920 face = (char *) data + offset;
921 else
922 face = "";
924 ++fonts;
926 fontdatalength = 58 + strlen (device) + strlen (face);
927 fontdata = (unsigned char *) res_alloc (fontdatalength);
928 memcpy (fontdata, data, 56);
929 strcpy ((char *) fontdata + 56, device);
930 strcpy ((char *) fontdata + 57 + strlen (device), face);
932 fd = (struct fontdir *) res_alloc (sizeof *fd);
933 fd->next = NULL;
934 fd->index = fonts;
935 fd->length = fontdatalength;
936 fd->data = fontdata;
938 for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next)
940 *pp = fd;
942 /* For the single fontdirs resource, we always use the resource
943 information of the last font. I don't know what else to do. */
944 fontdirs_resinfo = *resinfo;
947 /* Define the fontdirs resource. This is called after the entire rc
948 file has been parsed, if any font resources were seen. */
950 static void
951 define_fontdirs ()
953 struct res_resource *r;
954 struct res_id id;
956 id.named = 0;
957 id.u.id = 1;
959 r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
961 r->type = RES_TYPE_FONTDIR;
962 r->u.fontdir = fontdirs;
963 r->res_info = fontdirs_resinfo;
966 /* Define an icon resource. An icon file may contain a set of
967 bitmaps, each representing the same icon at various different
968 resolutions. They each get written out with a different ID. The
969 real icon resource is then a group resource which can be used to
970 select one of the actual icon bitmaps. */
972 void
973 define_icon (id, resinfo, filename)
974 struct res_id id;
975 const struct res_res_info *resinfo;
976 const char *filename;
978 FILE *e;
979 char *real_filename;
980 int type, count, i;
981 struct icondir *icondirs;
982 int first_icon;
983 struct res_resource *r;
984 struct group_icon *first, **pp;
986 e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename);
988 /* The start of an icon file is a three word structure. The first
989 word is ignored. The second word is the type of data. The third
990 word is the number of entries. */
992 get_word (e, real_filename);
993 type = get_word (e, real_filename);
994 count = get_word (e, real_filename);
995 if (type != 1)
996 fatal (_("icon file `%s' does not contain icon data"), real_filename);
998 /* Read in the icon directory entries. */
1000 icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
1002 for (i = 0; i < count; i++)
1004 icondirs[i].width = getc (e);
1005 icondirs[i].height = getc (e);
1006 icondirs[i].colorcount = getc (e);
1007 getc (e);
1008 icondirs[i].u.icon.planes = get_word (e, real_filename);
1009 icondirs[i].u.icon.bits = get_word (e, real_filename);
1010 icondirs[i].bytes = get_long (e, real_filename);
1011 icondirs[i].offset = get_long (e, real_filename);
1013 if (feof (e))
1014 unexpected_eof (real_filename);
1017 /* Define each icon as a unique resource. */
1019 first_icon = icons;
1021 for (i = 0; i < count; i++)
1023 unsigned char *data;
1024 struct res_id name;
1026 if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
1027 fatal (_("%s: fseek to %lu failed: %s"), real_filename,
1028 icondirs[i].offset, strerror (errno));
1030 data = (unsigned char *) res_alloc (icondirs[i].bytes);
1032 get_data (e, data, icondirs[i].bytes, real_filename);
1034 ++icons;
1036 name.named = 0;
1037 name.u.id = icons;
1039 r = define_standard_resource (&resources, RT_ICON, name,
1040 resinfo->language, 0);
1041 r->type = RES_TYPE_ICON;
1042 r->u.data.length = icondirs[i].bytes;
1043 r->u.data.data = data;
1044 r->res_info = *resinfo;
1047 fclose (e);
1048 free (real_filename);
1050 /* Define an icon group resource. */
1052 first = NULL;
1053 pp = &first;
1054 for (i = 0; i < count; i++)
1056 struct group_icon *cg;
1058 /* For some reason, at least in some files the planes and bits
1059 are zero. We instead set them from the color. This is
1060 copied from rcl. */
1062 cg = (struct group_icon *) res_alloc (sizeof *cg);
1063 cg->next = NULL;
1064 cg->width = icondirs[i].width;
1065 cg->height = icondirs[i].height;
1066 cg->colors = icondirs[i].colorcount;
1068 cg->planes = 1;
1069 cg->bits = 0;
1070 while ((1 << cg->bits) < cg->colors)
1071 ++cg->bits;
1073 cg->bytes = icondirs[i].bytes;
1074 cg->index = first_icon + i + 1;
1076 *pp = cg;
1077 pp = &(*pp)->next;
1080 free (icondirs);
1082 r = define_standard_resource (&resources, RT_GROUP_ICON, id,
1083 resinfo->language, 0);
1084 r->type = RES_TYPE_GROUP_ICON;
1085 r->u.group_icon = first;
1086 r->res_info = *resinfo;
1089 /* Define a menu resource. */
1091 void
1092 define_menu (id, resinfo, menuitems)
1093 struct res_id id;
1094 const struct res_res_info *resinfo;
1095 struct menuitem *menuitems;
1097 struct menu *m;
1098 struct res_resource *r;
1100 m = (struct menu *) res_alloc (sizeof *m);
1101 m->items = menuitems;
1102 m->help = 0;
1104 r = define_standard_resource (&resources, RT_MENU, id, resinfo->language, 0);
1105 r->type = RES_TYPE_MENU;
1106 r->u.menu = m;
1107 r->res_info = *resinfo;
1110 /* Define a menu item. This does not define a resource, but merely
1111 allocates and fills in a structure. */
1113 struct menuitem *
1114 define_menuitem (text, menuid, type, state, help, menuitems)
1115 const char *text;
1116 int menuid;
1117 unsigned long type;
1118 unsigned long state;
1119 unsigned long help;
1120 struct menuitem *menuitems;
1122 struct menuitem *mi;
1124 mi = (struct menuitem *) res_alloc (sizeof *mi);
1125 mi->next = NULL;
1126 mi->type = type;
1127 mi->state = state;
1128 mi->id = menuid;
1129 if (text == NULL)
1130 mi->text = NULL;
1131 else
1132 unicode_from_ascii ((int *) NULL, &mi->text, text);
1133 mi->help = help;
1134 mi->popup = menuitems;
1135 return mi;
1138 /* Define a messagetable resource. */
1140 void
1141 define_messagetable (id, resinfo, filename)
1142 struct res_id id;
1143 const struct res_res_info *resinfo;
1144 const char *filename;
1146 FILE *e;
1147 char *real_filename;
1148 struct stat s;
1149 unsigned char *data;
1150 struct res_resource *r;
1152 e = open_file_search (filename, FOPEN_RB, "messagetable file",
1153 &real_filename);
1155 if (stat (real_filename, &s) < 0)
1156 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
1157 strerror (errno));
1159 data = (unsigned char *) res_alloc (s.st_size);
1161 get_data (e, data, s.st_size, real_filename);
1163 fclose (e);
1164 free (real_filename);
1166 r = define_standard_resource (&resources, RT_MESSAGETABLE, id,
1167 resinfo->language, 0);
1169 r->type = RES_TYPE_MESSAGETABLE;
1170 r->u.data.length = s.st_size;
1171 r->u.data.data = data;
1172 r->res_info = *resinfo;
1175 /* Define an rcdata resource. */
1177 void
1178 define_rcdata (id, resinfo, data)
1179 struct res_id id;
1180 const struct res_res_info *resinfo;
1181 struct rcdata_item *data;
1183 struct res_resource *r;
1185 r = define_standard_resource (&resources, RT_RCDATA, id,
1186 resinfo->language, 0);
1187 r->type = RES_TYPE_RCDATA;
1188 r->u.rcdata = data;
1189 r->res_info = *resinfo;
1192 /* Create an rcdata item holding a string. */
1194 struct rcdata_item *
1195 define_rcdata_string (string, len)
1196 const char *string;
1197 unsigned long len;
1199 struct rcdata_item *ri;
1200 char *s;
1202 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
1203 ri->next = NULL;
1204 ri->type = RCDATA_STRING;
1205 ri->u.string.length = len;
1206 s = (char *) res_alloc (len);
1207 memcpy (s, string, len);
1208 ri->u.string.s = s;
1210 return ri;
1213 /* Create an rcdata item holding a number. */
1215 struct rcdata_item *
1216 define_rcdata_number (val, dword)
1217 unsigned long val;
1218 int dword;
1220 struct rcdata_item *ri;
1222 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
1223 ri->next = NULL;
1224 ri->type = dword ? RCDATA_DWORD : RCDATA_WORD;
1225 ri->u.word = val;
1227 return ri;
1230 /* Define a stringtable resource. This is called for each string
1231 which appears in a STRINGTABLE statement. */
1233 void
1234 define_stringtable (resinfo, stringid, string)
1235 const struct res_res_info *resinfo;
1236 unsigned long stringid;
1237 const char *string;
1239 struct res_id id;
1240 struct res_resource *r;
1242 id.named = 0;
1243 id.u.id = (stringid >> 4) + 1;
1244 r = define_standard_resource (&resources, RT_STRING, id,
1245 resinfo->language, 1);
1247 if (r->type == RES_TYPE_UNINITIALIZED)
1249 int i;
1251 r->type = RES_TYPE_STRINGTABLE;
1252 r->u.stringtable = ((struct stringtable *)
1253 res_alloc (sizeof (struct stringtable)));
1254 for (i = 0; i < 16; i++)
1256 r->u.stringtable->strings[i].length = 0;
1257 r->u.stringtable->strings[i].string = NULL;
1260 r->res_info = *resinfo;
1263 unicode_from_ascii (&r->u.stringtable->strings[stringid & 0xf].length,
1264 &r->u.stringtable->strings[stringid & 0xf].string,
1265 string);
1268 /* Define a user data resource where the data is in the rc file. */
1270 void
1271 define_user_data (id, type, resinfo, data)
1272 struct res_id id;
1273 struct res_id type;
1274 const struct res_res_info *resinfo;
1275 struct rcdata_item *data;
1277 struct res_id ids[3];
1278 struct res_resource *r;
1280 ids[0] = type;
1281 ids[1] = id;
1282 ids[2].named = 0;
1283 ids[2].u.id = resinfo->language;
1285 r = define_resource (&resources, 3, ids, 0);
1286 r->type = RES_TYPE_USERDATA;
1287 r->u.userdata = data;
1288 r->res_info = *resinfo;
1291 /* Define a user data resource where the data is in a file. */
1293 void
1294 define_user_file (id, type, resinfo, filename)
1295 struct res_id id;
1296 struct res_id type;
1297 const struct res_res_info *resinfo;
1298 const char *filename;
1300 FILE *e;
1301 char *real_filename;
1302 struct stat s;
1303 unsigned char *data;
1304 struct res_id ids[3];
1305 struct res_resource *r;
1307 e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
1309 if (stat (real_filename, &s) < 0)
1310 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
1311 strerror (errno));
1313 data = (unsigned char *) res_alloc (s.st_size);
1315 get_data (e, data, s.st_size, real_filename);
1317 fclose (e);
1318 free (real_filename);
1320 ids[0] = type;
1321 ids[1] = id;
1322 ids[2].named = 0;
1323 ids[2].u.id = resinfo->language;
1325 r = define_resource (&resources, 3, ids, 0);
1326 r->type = RES_TYPE_USERDATA;
1327 r->u.userdata = ((struct rcdata_item *)
1328 res_alloc (sizeof (struct rcdata_item)));
1329 r->u.userdata->next = NULL;
1330 r->u.userdata->type = RCDATA_BUFFER;
1331 r->u.userdata->u.buffer.length = s.st_size;
1332 r->u.userdata->u.buffer.data = data;
1333 r->res_info = *resinfo;
1336 /* Define a versioninfo resource. */
1338 void
1339 define_versioninfo (id, language, fixedverinfo, verinfo)
1340 struct res_id id;
1341 int language;
1342 struct fixed_versioninfo *fixedverinfo;
1343 struct ver_info *verinfo;
1345 struct res_resource *r;
1347 r = define_standard_resource (&resources, RT_VERSION, id, language, 0);
1348 r->type = RES_TYPE_VERSIONINFO;
1349 r->u.versioninfo = ((struct versioninfo *)
1350 res_alloc (sizeof (struct versioninfo)));
1351 r->u.versioninfo->fixed = fixedverinfo;
1352 r->u.versioninfo->var = verinfo;
1353 r->res_info.language = language;
1356 /* Add string version info to a list of version information. */
1358 struct ver_info *
1359 append_ver_stringfileinfo (verinfo, language, strings)
1360 struct ver_info *verinfo;
1361 const char *language;
1362 struct ver_stringinfo *strings;
1364 struct ver_info *vi, **pp;
1366 vi = (struct ver_info *) res_alloc (sizeof *vi);
1367 vi->next = NULL;
1368 vi->type = VERINFO_STRING;
1369 unicode_from_ascii ((int *) NULL, &vi->u.string.language, language);
1370 vi->u.string.strings = strings;
1372 for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1374 *pp = vi;
1376 return verinfo;
1379 /* Add variable version info to a list of version information. */
1381 struct ver_info *
1382 append_ver_varfileinfo (verinfo, key, var)
1383 struct ver_info *verinfo;
1384 const char *key;
1385 struct ver_varinfo *var;
1387 struct ver_info *vi, **pp;
1389 vi = (struct ver_info *) res_alloc (sizeof *vi);
1390 vi->next = NULL;
1391 vi->type = VERINFO_VAR;
1392 unicode_from_ascii ((int *) NULL, &vi->u.var.key, key);
1393 vi->u.var.var = var;
1395 for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1397 *pp = vi;
1399 return verinfo;
1402 /* Append version string information to a list. */
1404 struct ver_stringinfo *
1405 append_verval (strings, key, value)
1406 struct ver_stringinfo *strings;
1407 const char *key;
1408 const char *value;
1410 struct ver_stringinfo *vs, **pp;
1412 vs = (struct ver_stringinfo *) res_alloc (sizeof *vs);
1413 vs->next = NULL;
1414 unicode_from_ascii ((int *) NULL, &vs->key, key);
1415 unicode_from_ascii ((int *) NULL, &vs->value, value);
1417 for (pp = &strings; *pp != NULL; pp = &(*pp)->next)
1419 *pp = vs;
1421 return strings;
1424 /* Append version variable information to a list. */
1426 struct ver_varinfo *
1427 append_vertrans (var, language, charset)
1428 struct ver_varinfo *var;
1429 unsigned long language;
1430 unsigned long charset;
1432 struct ver_varinfo *vv, **pp;
1434 vv = (struct ver_varinfo *) res_alloc (sizeof *vv);
1435 vv->next = NULL;
1436 vv->language = language;
1437 vv->charset = charset;
1439 for (pp = &var; *pp != NULL; pp = &(*pp)->next)
1441 *pp = vv;
1443 return var;
1446 /* Local functions used to write out an rc file. */
1448 static void indent PARAMS ((FILE *, int));
1449 static void write_rc_directory
1450 PARAMS ((FILE *, const struct res_directory *, const struct res_id *,
1451 const struct res_id *, int *, int));
1452 static void write_rc_subdir
1453 PARAMS ((FILE *, const struct res_entry *, const struct res_id *,
1454 const struct res_id *, int *, int));
1455 static void write_rc_resource
1456 PARAMS ((FILE *, const struct res_id *, const struct res_id *,
1457 const struct res_resource *, int *));
1458 static void write_rc_accelerators
1459 PARAMS ((FILE *, const struct accelerator *));
1460 static void write_rc_cursor PARAMS ((FILE *, const struct cursor *));
1461 static void write_rc_group_cursor
1462 PARAMS ((FILE *, const struct group_cursor *));
1463 static void write_rc_dialog PARAMS ((FILE *, const struct dialog *));
1464 static void write_rc_dialog_control
1465 PARAMS ((FILE *, const struct dialog_control *));
1466 static void write_rc_fontdir PARAMS ((FILE *, const struct fontdir *));
1467 static void write_rc_group_icon PARAMS ((FILE *, const struct group_icon *));
1468 static void write_rc_menu PARAMS ((FILE *, const struct menu *, int));
1469 static void write_rc_menuitems
1470 PARAMS ((FILE *, const struct menuitem *, int, int));
1471 static void write_rc_rcdata PARAMS ((FILE *, const struct rcdata_item *, int));
1472 static void write_rc_stringtable
1473 PARAMS ((FILE *, const struct res_id *, const struct stringtable *));
1474 static void write_rc_versioninfo PARAMS ((FILE *, const struct versioninfo *));
1475 static void write_rc_filedata
1476 PARAMS ((FILE *, unsigned long, const unsigned char *));
1478 /* Indent a given number of spaces. */
1480 static void
1481 indent (e, c)
1482 FILE *e;
1483 int c;
1485 int i;
1487 for (i = 0; i < c; i++)
1488 putc (' ', e);
1491 /* Dump the resources we have read in the format of an rc file.
1493 Actually, we don't use the format of an rc file, because it's way
1494 too much of a pain--for example, we'd have to write icon resources
1495 into a file and refer to that file. We just generate a readable
1496 format that kind of looks like an rc file, and is useful for
1497 understanding the contents of a resource file. Someday we may want
1498 to generate an rc file which the rc compiler can read; if that day
1499 comes, this code will have to be fixed up. */
1501 void
1502 write_rc_file (filename, resources)
1503 const char *filename;
1504 const struct res_directory *resources;
1506 FILE *e;
1507 int language;
1509 if (filename == NULL)
1510 e = stdout;
1511 else
1513 e = fopen (filename, FOPEN_WT);
1514 if (e == NULL)
1515 fatal (_("can't open `%s' for output: %s"), filename, strerror (errno));
1518 language = -1;
1519 write_rc_directory (e, resources, (const struct res_id *) NULL,
1520 (const struct res_id *) NULL, &language, 1);
1523 /* Write out a directory. E is the file to write to. RD is the
1524 directory. TYPE is a pointer to the level 1 ID which serves as the
1525 resource type. NAME is a pointer to the level 2 ID which serves as
1526 an individual resource name. LANGUAGE is a pointer to the current
1527 language. LEVEL is the level in the tree. */
1529 static void
1530 write_rc_directory (e, rd, type, name, language, level)
1531 FILE *e;
1532 const struct res_directory *rd;
1533 const struct res_id *type;
1534 const struct res_id *name;
1535 int *language;
1536 int level;
1538 const struct res_entry *re;
1540 /* Print out some COFF information that rc files can't represent. */
1542 if (rd->time != 0)
1543 fprintf (e, "// Time stamp: %lu\n", rd->time);
1544 if (rd->characteristics != 0)
1545 fprintf (e, "// Characteristics: %lu\n", rd->characteristics);
1546 if (rd->major != 0 || rd->minor != 0)
1547 fprintf (e, "// Version: %d %d\n", rd->major, rd->minor);
1549 for (re = rd->entries; re != NULL; re = re->next)
1551 switch (level)
1553 case 1:
1554 /* If we're at level 1, the key of this resource is the
1555 type. This normally duplicates the information we have
1556 stored with the resource itself, but we need to remember
1557 the type if this is a user define resource type. */
1558 type = &re->id;
1559 break;
1561 case 2:
1562 /* If we're at level 2, the key of this resource is the name
1563 we are going to use in the rc printout. */
1564 name = &re->id;
1565 break;
1567 case 3:
1568 /* If we're at level 3, then this key represents a language.
1569 Use it to update the current language. */
1570 if (! re->id.named
1571 && re->id.u.id != (unsigned long) (unsigned int) *language
1572 && (re->id.u.id & 0xffff) == re->id.u.id)
1574 fprintf (e, "LANGUAGE %lu, %lu\n",
1575 re->id.u.id & 0xff, (re->id.u.id >> 8) & 0xff);
1576 *language = re->id.u.id;
1578 break;
1580 default:
1581 break;
1584 if (re->subdir)
1585 write_rc_subdir (e, re, type, name, language, level);
1586 else
1588 if (level == 3)
1590 /* This is the normal case: the three levels are
1591 TYPE/NAME/LANGUAGE. NAME will have been set at level
1592 2, and represents the name to use. We probably just
1593 set LANGUAGE, and it will probably match what the
1594 resource itself records if anything. */
1595 write_rc_resource (e, type, name, re->u.res, language);
1597 else
1599 fprintf (e, "// Resource at unexpected level %d\n", level);
1600 write_rc_resource (e, type, (struct res_id *) NULL, re->u.res,
1601 language);
1607 /* Write out a subdirectory entry. E is the file to write to. RE is
1608 the subdirectory entry. TYPE and NAME are pointers to higher level
1609 IDs, or NULL. LANGUAGE is a pointer to the current language.
1610 LEVEL is the level in the tree. */
1612 static void
1613 write_rc_subdir (e, re, type, name, language, level)
1614 FILE *e;
1615 const struct res_entry *re;
1616 const struct res_id *type;
1617 const struct res_id *name;
1618 int *language;
1619 int level;
1621 fprintf (e, "\n");
1622 switch (level)
1624 case 1:
1625 fprintf (e, "// Type: ");
1626 if (re->id.named)
1627 res_id_print (e, re->id, 1);
1628 else
1630 const char *s;
1632 switch (re->id.u.id)
1634 case RT_CURSOR: s = "cursor"; break;
1635 case RT_BITMAP: s = "bitmap"; break;
1636 case RT_ICON: s = "icon"; break;
1637 case RT_MENU: s = "menu"; break;
1638 case RT_DIALOG: s = "dialog"; break;
1639 case RT_STRING: s = "stringtable"; break;
1640 case RT_FONTDIR: s = "fontdir"; break;
1641 case RT_FONT: s = "font"; break;
1642 case RT_ACCELERATOR: s = "accelerators"; break;
1643 case RT_RCDATA: s = "rcdata"; break;
1644 case RT_MESSAGETABLE: s = "messagetable"; break;
1645 case RT_GROUP_CURSOR: s = "group cursor"; break;
1646 case RT_GROUP_ICON: s = "group icon"; break;
1647 case RT_VERSION: s = "version"; break;
1648 case RT_DLGINCLUDE: s = "dlginclude"; break;
1649 case RT_PLUGPLAY: s = "plugplay"; break;
1650 case RT_VXD: s = "vxd"; break;
1651 case RT_ANICURSOR: s = "anicursor"; break;
1652 case RT_ANIICON: s = "aniicon"; break;
1653 default: s = NULL; break;
1656 if (s != NULL)
1657 fprintf (e, "%s", s);
1658 else
1659 res_id_print (e, re->id, 1);
1661 fprintf (e, "\n");
1662 break;
1664 case 2:
1665 fprintf (e, "// Name: ");
1666 res_id_print (e, re->id, 1);
1667 fprintf (e, "\n");
1668 break;
1670 case 3:
1671 fprintf (e, "// Language: ");
1672 res_id_print (e, re->id, 1);
1673 fprintf (e, "\n");
1674 break;
1676 default:
1677 fprintf (e, "// Level %d: ", level);
1678 res_id_print (e, re->id, 1);
1679 fprintf (e, "\n");
1682 write_rc_directory (e, re->u.dir, type, name, language, level + 1);
1685 /* Write out a single resource. E is the file to write to. TYPE is a
1686 pointer to the type of the resource. NAME is a pointer to the name
1687 of the resource; it will be NULL if there is a level mismatch. RES
1688 is the resource data. LANGUAGE is a pointer to the current
1689 language. */
1691 static void
1692 write_rc_resource (e, type, name, res, language)
1693 FILE *e;
1694 const struct res_id *type;
1695 const struct res_id *name;
1696 const struct res_resource *res;
1697 int *language;
1699 const char *s;
1700 int rt;
1701 int menuex = 0;
1703 fprintf (e, "\n");
1705 switch (res->type)
1707 default:
1708 abort ();
1710 case RES_TYPE_ACCELERATOR:
1711 s = "ACCELERATOR";
1712 rt = RT_ACCELERATOR;
1713 break;
1715 case RES_TYPE_BITMAP:
1716 s = "BITMAP";
1717 rt = RT_BITMAP;
1718 break;
1720 case RES_TYPE_CURSOR:
1721 s = "CURSOR";
1722 rt = RT_CURSOR;
1723 break;
1725 case RES_TYPE_GROUP_CURSOR:
1726 s = "GROUP_CURSOR";
1727 rt = RT_GROUP_CURSOR;
1728 break;
1730 case RES_TYPE_DIALOG:
1731 if (extended_dialog (res->u.dialog))
1732 s = "DIALOGEX";
1733 else
1734 s = "DIALOG";
1735 rt = RT_DIALOG;
1736 break;
1738 case RES_TYPE_FONT:
1739 s = "FONT";
1740 rt = RT_FONT;
1741 break;
1743 case RES_TYPE_FONTDIR:
1744 s = "FONTDIR";
1745 rt = RT_FONTDIR;
1746 break;
1748 case RES_TYPE_ICON:
1749 s = "ICON";
1750 rt = RT_ICON;
1751 break;
1753 case RES_TYPE_GROUP_ICON:
1754 s = "GROUP_ICON";
1755 rt = RT_GROUP_ICON;
1756 break;
1758 case RES_TYPE_MENU:
1759 if (extended_menu (res->u.menu))
1761 s = "MENUEX";
1762 menuex = 1;
1764 else
1766 s = "MENU";
1767 menuex = 0;
1769 rt = RT_MENU;
1770 break;
1772 case RES_TYPE_MESSAGETABLE:
1773 s = "MESSAGETABLE";
1774 rt = RT_MESSAGETABLE;
1775 break;
1777 case RES_TYPE_RCDATA:
1778 s = "RCDATA";
1779 rt = RT_RCDATA;
1780 break;
1782 case RES_TYPE_STRINGTABLE:
1783 s = "STRINGTABLE";
1784 rt = RT_STRING;
1785 break;
1787 case RES_TYPE_USERDATA:
1788 s = NULL;
1789 rt = 0;
1790 break;
1792 case RES_TYPE_VERSIONINFO:
1793 s = "VERSIONINFO";
1794 rt = RT_VERSION;
1795 break;
1798 if (rt != 0
1799 && type != NULL
1800 && (type->named || type->u.id != (unsigned long) rt))
1802 fprintf (e, "// Unexpected resource type mismatch: ");
1803 res_id_print (e, *type, 1);
1804 fprintf (e, " != %d", rt);
1807 if (res->coff_info.codepage != 0)
1808 fprintf (e, "// Code page: %lu\n", res->coff_info.codepage);
1809 if (res->coff_info.reserved != 0)
1810 fprintf (e, "// COFF reserved value: %lu\n", res->coff_info.reserved);
1812 if (name != NULL)
1813 res_id_print (e, *name, 0);
1814 else
1815 fprintf (e, "??Unknown-Name??");
1817 fprintf (e, " ");
1818 if (s != NULL)
1819 fprintf (e, "%s", s);
1820 else if (type != NULL)
1821 res_id_print (e, *type, 0);
1822 else
1823 fprintf (e, "??Unknown-Type??");
1825 if (res->res_info.memflags != 0)
1827 if ((res->res_info.memflags & MEMFLAG_MOVEABLE) != 0)
1828 fprintf (e, " MOVEABLE");
1829 if ((res->res_info.memflags & MEMFLAG_PURE) != 0)
1830 fprintf (e, " PURE");
1831 if ((res->res_info.memflags & MEMFLAG_PRELOAD) != 0)
1832 fprintf (e, " PRELOAD");
1833 if ((res->res_info.memflags & MEMFLAG_DISCARDABLE) != 0)
1834 fprintf (e, " DISCARDABLE");
1837 if (res->type == RES_TYPE_DIALOG)
1839 fprintf (e, " %d, %d, %d, %d", res->u.dialog->x, res->u.dialog->y,
1840 res->u.dialog->width, res->u.dialog->height);
1841 if (res->u.dialog->ex != NULL
1842 && res->u.dialog->ex->help != 0)
1843 fprintf (e, ", %lu", res->u.dialog->ex->help);
1846 fprintf (e, "\n");
1848 if ((res->res_info.language != 0 && res->res_info.language != *language)
1849 || res->res_info.characteristics != 0
1850 || res->res_info.version != 0)
1852 int modifiers;
1854 switch (res->type)
1856 case RES_TYPE_ACCELERATOR:
1857 case RES_TYPE_DIALOG:
1858 case RES_TYPE_MENU:
1859 case RES_TYPE_RCDATA:
1860 case RES_TYPE_STRINGTABLE:
1861 modifiers = 1;
1862 break;
1864 default:
1865 modifiers = 0;
1866 break;
1869 if (res->res_info.language != 0 && res->res_info.language != *language)
1870 fprintf (e, "%sLANGUAGE %d, %d\n",
1871 modifiers ? "// " : "",
1872 res->res_info.language & 0xff,
1873 (res->res_info.language >> 8) & 0xff);
1874 if (res->res_info.characteristics != 0)
1875 fprintf (e, "%sCHARACTERISTICS %lu\n",
1876 modifiers ? "// " : "",
1877 res->res_info.characteristics);
1878 if (res->res_info.version != 0)
1879 fprintf (e, "%sVERSION %lu\n",
1880 modifiers ? "// " : "",
1881 res->res_info.version);
1884 switch (res->type)
1886 default:
1887 abort ();
1889 case RES_TYPE_ACCELERATOR:
1890 write_rc_accelerators (e, res->u.acc);
1891 break;
1893 case RES_TYPE_CURSOR:
1894 write_rc_cursor (e, res->u.cursor);
1895 break;
1897 case RES_TYPE_GROUP_CURSOR:
1898 write_rc_group_cursor (e, res->u.group_cursor);
1899 break;
1901 case RES_TYPE_DIALOG:
1902 write_rc_dialog (e, res->u.dialog);
1903 break;
1905 case RES_TYPE_FONTDIR:
1906 write_rc_fontdir (e, res->u.fontdir);
1907 break;
1909 case RES_TYPE_GROUP_ICON:
1910 write_rc_group_icon (e, res->u.group_icon);
1911 break;
1913 case RES_TYPE_MENU:
1914 write_rc_menu (e, res->u.menu, menuex);
1915 break;
1917 case RES_TYPE_RCDATA:
1918 write_rc_rcdata (e, res->u.rcdata, 0);
1919 break;
1921 case RES_TYPE_STRINGTABLE:
1922 write_rc_stringtable (e, name, res->u.stringtable);
1923 break;
1925 case RES_TYPE_USERDATA:
1926 write_rc_rcdata (e, res->u.userdata, 0);
1927 break;
1929 case RES_TYPE_VERSIONINFO:
1930 write_rc_versioninfo (e, res->u.versioninfo);
1931 break;
1933 case RES_TYPE_BITMAP:
1934 case RES_TYPE_FONT:
1935 case RES_TYPE_ICON:
1936 case RES_TYPE_MESSAGETABLE:
1937 write_rc_filedata (e, res->u.data.length, res->u.data.data);
1938 break;
1942 /* Write out accelerator information. */
1944 static void
1945 write_rc_accelerators (e, accelerators)
1946 FILE *e;
1947 const struct accelerator *accelerators;
1949 const struct accelerator *acc;
1951 fprintf (e, "BEGIN\n");
1952 for (acc = accelerators; acc != NULL; acc = acc->next)
1954 int printable;
1956 fprintf (e, " ");
1958 if ((acc->key & 0x7f) == acc->key
1959 && isprint ((unsigned char) acc->key)
1960 && (acc->flags & ACC_VIRTKEY) == 0)
1962 fprintf (e, "\"%c\"", acc->key);
1963 printable = 1;
1965 else
1967 fprintf (e, "%d", acc->key);
1968 printable = 0;
1971 fprintf (e, ", %d", acc->id);
1973 if (! printable)
1975 if ((acc->flags & ACC_VIRTKEY) != 0)
1976 fprintf (e, ", VIRTKEY");
1977 else
1978 fprintf (e, ", ASCII");
1981 if ((acc->flags & ACC_SHIFT) != 0)
1982 fprintf (e, ", SHIFT");
1983 if ((acc->flags & ACC_CONTROL) != 0)
1984 fprintf (e, ", CONTROL");
1985 if ((acc->flags & ACC_ALT) != 0)
1986 fprintf (e, ", ALT");
1988 fprintf (e, "\n");
1991 fprintf (e, "END\n");
1994 /* Write out cursor information. This would normally be in a separate
1995 file, which the rc file would include. */
1997 static void
1998 write_rc_cursor (e, cursor)
1999 FILE *e;
2000 const struct cursor *cursor;
2002 fprintf (e, "// Hotspot: x: %d; y: %d\n", cursor->xhotspot,
2003 cursor->yhotspot);
2004 write_rc_filedata (e, cursor->length, cursor->data);
2007 /* Write out group cursor data. This would normally be built from the
2008 cursor data. */
2010 static void
2011 write_rc_group_cursor (e, group_cursor)
2012 FILE *e;
2013 const struct group_cursor *group_cursor;
2015 const struct group_cursor *gc;
2017 for (gc = group_cursor; gc != NULL; gc = gc->next)
2019 fprintf (e, "// width: %d; height %d; planes %d; bits %d\n",
2020 gc->width, gc->height, gc->planes, gc->bits);
2021 fprintf (e, "// data bytes: %lu; index: %d\n",
2022 gc->bytes, gc->index);
2026 /* Write dialog data. */
2028 static void
2029 write_rc_dialog (e, dialog)
2030 FILE *e;
2031 const struct dialog *dialog;
2033 const struct dialog_control *control;
2035 if (dialog->style != 0)
2036 fprintf (e, "STYLE 0x%lx\n", dialog->style);
2037 if (dialog->exstyle != 0)
2038 fprintf (e, "EXSTYLE 0x%lx\n", dialog->exstyle);
2039 if ((dialog->class.named && dialog->class.u.n.length > 0)
2040 || dialog->class.u.id != 0)
2042 fprintf (e, "CLASS ");
2043 res_id_print (e, dialog->class, 0);
2044 fprintf (e, "\n");
2046 if (dialog->caption != NULL)
2048 fprintf (e, "CAPTION \"");
2049 unicode_print (e, dialog->caption, -1);
2050 fprintf (e, "\"\n");
2052 if ((dialog->menu.named && dialog->menu.u.n.length > 0)
2053 || dialog->menu.u.id != 0)
2055 fprintf (e, "MENU ");
2056 res_id_print (e, dialog->menu, 0);
2057 fprintf (e, "\n");
2059 if (dialog->font != NULL)
2061 fprintf (e, "FONT %d, \"", dialog->pointsize);
2062 unicode_print (e, dialog->font, -1);
2063 fprintf (e, "\"");
2064 if (dialog->ex != NULL
2065 && (dialog->ex->weight != 0 || dialog->ex->italic != 0))
2066 fprintf (e, ", %d, %d", dialog->ex->weight, dialog->ex->italic);
2067 fprintf (e, "\n");
2070 fprintf (e, "BEGIN\n");
2072 for (control = dialog->controls; control != NULL; control = control->next)
2073 write_rc_dialog_control (e, control);
2075 fprintf (e, "END\n");
2078 /* For each predefined control keyword, this table provides the class
2079 and the style. */
2081 struct control_info
2083 const char *name;
2084 unsigned short class;
2085 unsigned long style;
2088 static const struct control_info control_info[] =
2090 { "AUTO3STATE", CTL_BUTTON, BS_AUTO3STATE },
2091 { "AUTOCHECKBOX", CTL_BUTTON, BS_AUTOCHECKBOX },
2092 { "AUTORADIOBUTTON", CTL_BUTTON, BS_AUTORADIOBUTTON },
2093 { "CHECKBOX", CTL_BUTTON, BS_CHECKBOX },
2094 { "COMBOBOX", CTL_COMBOBOX, (unsigned long) -1 },
2095 { "CTEXT", CTL_STATIC, SS_CENTER },
2096 { "DEFPUSHBUTTON", CTL_BUTTON, BS_DEFPUSHBUTTON },
2097 { "EDITTEXT", CTL_EDIT, (unsigned long) -1 },
2098 { "GROUPBOX", CTL_BUTTON, BS_GROUPBOX },
2099 { "ICON", CTL_STATIC, SS_ICON },
2100 { "LISTBOX", CTL_LISTBOX, (unsigned long) -1 },
2101 { "LTEXT", CTL_STATIC, SS_LEFT },
2102 { "PUSHBOX", CTL_BUTTON, BS_PUSHBOX },
2103 { "PUSHBUTTON", CTL_BUTTON, BS_PUSHBUTTON },
2104 { "RADIOBUTTON", CTL_BUTTON, BS_RADIOBUTTON },
2105 { "RTEXT", CTL_STATIC, SS_RIGHT },
2106 { "SCROLLBAR", CTL_SCROLLBAR, (unsigned long) -1 },
2107 { "STATE3", CTL_BUTTON, BS_3STATE },
2108 /* It's important that USERBUTTON come after all the other button
2109 types, so that it won't be matched too early. */
2110 { "USERBUTTON", CTL_BUTTON, (unsigned long) -1 },
2111 { NULL, 0, 0 }
2114 /* Write a dialog control. */
2116 static void
2117 write_rc_dialog_control (e, control)
2118 FILE *e;
2119 const struct dialog_control *control;
2121 const struct control_info *ci;
2123 fprintf (e, " ");
2125 if (control->class.named)
2126 ci = NULL;
2127 else
2129 for (ci = control_info; ci->name != NULL; ++ci)
2130 if (ci->class == control->class.u.id
2131 && (ci->style == (unsigned long) -1
2132 || ci->style == (control->style & 0xff)))
2133 break;
2135 if (ci == NULL)
2136 fprintf (e, "CONTROL");
2137 else if (ci->name != NULL)
2138 fprintf (e, "%s", ci->name);
2139 else
2140 fprintf (e, "CONTROL");
2142 if (control->text.named || control->text.u.id != 0)
2144 fprintf (e, " ");
2145 res_id_print (e, control->text, 1);
2146 fprintf (e, ",");
2149 fprintf (e, " %d, ", control->id);
2151 if (ci == NULL)
2153 if (control->class.named)
2154 fprintf (e, "\"");
2155 res_id_print (e, control->class, 0);
2156 if (control->class.named)
2157 fprintf (e, "\"");
2158 fprintf (e, ", 0x%lx, ", control->style);
2161 fprintf (e, "%d, %d", control->x, control->y);
2163 if (control->style != SS_ICON
2164 || control->exstyle != 0
2165 || control->width != 0
2166 || control->height != 0
2167 || control->help != 0)
2169 fprintf (e, ", %d, %d", control->width, control->height);
2171 /* FIXME: We don't need to print the style if it is the default.
2172 More importantly, in certain cases we actually need to turn
2173 off parts of the forced style, by using NOT. */
2174 fprintf (e, ", 0x%lx", control->style);
2176 if (control->exstyle != 0 || control->help != 0)
2177 fprintf (e, ", 0x%lx, %lu", control->exstyle, control->help);
2180 fprintf (e, "\n");
2182 if (control->data != NULL)
2183 write_rc_rcdata (e, control->data, 2);
2186 /* Write out font directory data. This would normally be built from
2187 the font data. */
2189 static void
2190 write_rc_fontdir (e, fontdir)
2191 FILE *e;
2192 const struct fontdir *fontdir;
2194 const struct fontdir *fc;
2196 for (fc = fontdir; fc != NULL; fc = fc->next)
2198 fprintf (e, "// Font index: %d\n", fc->index);
2199 write_rc_filedata (e, fc->length, fc->data);
2203 /* Write out group icon data. This would normally be built from the
2204 icon data. */
2206 static void
2207 write_rc_group_icon (e, group_icon)
2208 FILE *e;
2209 const struct group_icon *group_icon;
2211 const struct group_icon *gi;
2213 for (gi = group_icon; gi != NULL; gi = gi->next)
2215 fprintf (e, "// width: %d; height %d; colors: %d; planes %d; bits %d\n",
2216 gi->width, gi->height, gi->colors, gi->planes, gi->bits);
2217 fprintf (e, "// data bytes: %lu; index: %d\n",
2218 gi->bytes, gi->index);
2222 /* Write out a menu resource. */
2224 static void
2225 write_rc_menu (e, menu, menuex)
2226 FILE *e;
2227 const struct menu *menu;
2228 int menuex;
2230 if (menu->help != 0)
2231 fprintf (e, "// Help ID: %lu\n", menu->help);
2232 write_rc_menuitems (e, menu->items, menuex, 0);
2235 /* Write out menuitems. */
2237 static void
2238 write_rc_menuitems (e, menuitems, menuex, ind)
2239 FILE *e;
2240 const struct menuitem *menuitems;
2241 int menuex;
2242 int ind;
2244 const struct menuitem *mi;
2246 indent (e, ind);
2247 fprintf (e, "BEGIN\n");
2249 for (mi = menuitems; mi != NULL; mi = mi->next)
2251 indent (e, ind + 2);
2253 if (mi->popup == NULL)
2254 fprintf (e, "MENUITEM");
2255 else
2256 fprintf (e, "POPUP");
2258 if (! menuex
2259 && mi->popup == NULL
2260 && mi->text == NULL
2261 && mi->type == 0
2262 && mi->id == 0)
2264 fprintf (e, " SEPARATOR\n");
2265 continue;
2268 if (mi->text == NULL)
2269 fprintf (e, " \"\"");
2270 else
2272 fprintf (e, " \"");
2273 unicode_print (e, mi->text, -1);
2274 fprintf (e, "\"");
2277 if (! menuex)
2279 if (mi->popup == NULL)
2280 fprintf (e, ", %d", mi->id);
2282 if ((mi->type & MENUITEM_CHECKED) != 0)
2283 fprintf (e, ", CHECKED");
2284 if ((mi->type & MENUITEM_GRAYED) != 0)
2285 fprintf (e, ", GRAYED");
2286 if ((mi->type & MENUITEM_HELP) != 0)
2287 fprintf (e, ", HELP");
2288 if ((mi->type & MENUITEM_INACTIVE) != 0)
2289 fprintf (e, ", INACTIVE");
2290 if ((mi->type & MENUITEM_MENUBARBREAK) != 0)
2291 fprintf (e, ", MENUBARBREAK");
2292 if ((mi->type & MENUITEM_MENUBREAK) != 0)
2293 fprintf (e, ", MENUBREAK");
2295 else
2297 if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0)
2299 fprintf (e, ", %d", mi->id);
2300 if (mi->type != 0 || mi->state != 0 || mi->help != 0)
2302 fprintf (e, ", %lu", mi->type);
2303 if (mi->state != 0 || mi->help != 0)
2305 fprintf (e, ", %lu", mi->state);
2306 if (mi->help != 0)
2307 fprintf (e, ", %lu", mi->help);
2313 fprintf (e, "\n");
2315 if (mi->popup != NULL)
2316 write_rc_menuitems (e, mi->popup, menuex, ind + 2);
2319 indent (e, ind);
2320 fprintf (e, "END\n");
2323 /* Write out an rcdata resource. This is also used for other types of
2324 resources that need to print arbitrary data. */
2326 static void
2327 write_rc_rcdata (e, rcdata, ind)
2328 FILE *e;
2329 const struct rcdata_item *rcdata;
2330 int ind;
2332 const struct rcdata_item *ri;
2334 indent (e, ind);
2335 fprintf (e, "BEGIN\n");
2337 for (ri = rcdata; ri != NULL; ri = ri->next)
2339 if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0)
2340 continue;
2342 indent (e, ind + 2);
2344 switch (ri->type)
2346 default:
2347 abort ();
2349 case RCDATA_WORD:
2350 fprintf (e, "%d", ri->u.word);
2351 break;
2353 case RCDATA_DWORD:
2354 fprintf (e, "%luL", ri->u.dword);
2355 break;
2357 case RCDATA_STRING:
2359 const char *s;
2360 unsigned long i;
2362 fprintf (e, "\"");
2363 s = ri->u.string.s;
2364 for (i = 0; i < ri->u.string.length; i++)
2366 if (isprint ((unsigned char) *s))
2367 putc (*s, e);
2368 else
2369 fprintf (e, "\\%03o", *s);
2371 fprintf (e, "\"");
2372 break;
2375 case RCDATA_WSTRING:
2376 fprintf (e, "L\"");
2377 unicode_print (e, ri->u.wstring.w, ri->u.wstring.length);
2378 fprintf (e, "\"");
2379 break;
2381 case RCDATA_BUFFER:
2383 unsigned long i;
2384 int first;
2386 /* Assume little endian data. */
2388 first = 1;
2389 for (i = 0; i + 3 < ri->u.buffer.length; i += 4)
2391 unsigned long l;
2392 int j;
2394 if (! first)
2395 indent (e, ind + 2);
2396 l = ((((((ri->u.buffer.data[i + 3] << 8)
2397 | ri->u.buffer.data[i + 2]) << 8)
2398 | ri->u.buffer.data[i + 1]) << 8)
2399 | ri->u.buffer.data[i]);
2400 fprintf (e, "%luL", l);
2401 if (i + 4 < ri->u.buffer.length || ri->next != NULL)
2402 fprintf (e, ",");
2403 for (j = 0; j < 4; ++j)
2404 if (! isprint (ri->u.buffer.data[i + j])
2405 && ri->u.buffer.data[i + j] != 0)
2406 break;
2407 if (j >= 4)
2409 fprintf (e, "\t// ");
2410 for (j = 0; j < 4; ++j)
2412 if (! isprint (ri->u.buffer.data[i + j]))
2413 fprintf (e, "\\%03o", ri->u.buffer.data[i + j]);
2414 else
2416 if (ri->u.buffer.data[i + j] == '\\')
2417 fprintf (e, "\\");
2418 fprintf (e, "%c", ri->u.buffer.data[i + j]);
2422 fprintf (e, "\n");
2423 first = 0;
2426 if (i + 1 < ri->u.buffer.length)
2428 int s;
2429 int j;
2431 if (! first)
2432 indent (e, ind + 2);
2433 s = (ri->u.buffer.data[i + 1] << 8) | ri->u.buffer.data[i];
2434 fprintf (e, "%d", s);
2435 if (i + 2 < ri->u.buffer.length || ri->next != NULL)
2436 fprintf (e, ",");
2437 for (j = 0; j < 2; ++j)
2438 if (! isprint (ri->u.buffer.data[i + j])
2439 && ri->u.buffer.data[i + j] != 0)
2440 break;
2441 if (j >= 2)
2443 fprintf (e, "\t// ");
2444 for (j = 0; j < 2; ++j)
2446 if (! isprint (ri->u.buffer.data[i + j]))
2447 fprintf (e, "\\%03o", ri->u.buffer.data[i + j]);
2448 else
2450 if (ri->u.buffer.data[i + j] == '\\')
2451 fprintf (e, "\\");
2452 fprintf (e, "%c", ri->u.buffer.data[i + j]);
2456 fprintf (e, "\n");
2457 i += 2;
2458 first = 0;
2461 if (i < ri->u.buffer.length)
2463 if (! first)
2464 indent (e, ind + 2);
2465 if ((ri->u.buffer.data[i] & 0x7f) == ri->u.buffer.data[i]
2466 && isprint (ri->u.buffer.data[i]))
2467 fprintf (e, "\"%c\"", ri->u.buffer.data[i]);
2468 else
2469 fprintf (e, "\"\\%03o\"", ri->u.buffer.data[i]);
2470 if (ri->next != NULL)
2471 fprintf (e, ",");
2472 fprintf (e, "\n");
2473 first = 0;
2476 break;
2480 if (ri->type != RCDATA_BUFFER)
2482 if (ri->next != NULL)
2483 fprintf (e, ",");
2484 fprintf (e, "\n");
2488 indent (e, ind);
2489 fprintf (e, "END\n");
2492 /* Write out a stringtable resource. */
2494 static void
2495 write_rc_stringtable (e, name, stringtable)
2496 FILE *e;
2497 const struct res_id *name;
2498 const struct stringtable *stringtable;
2500 unsigned long offset;
2501 int i;
2503 if (name != NULL && ! name->named)
2504 offset = (name->u.id - 1) << 4;
2505 else
2507 fprintf (e, "// %s string table name\n",
2508 name == NULL ? "Missing" : "Invalid");
2509 offset = 0;
2512 fprintf (e, "BEGIN\n");
2514 for (i = 0; i < 16; i++)
2516 if (stringtable->strings[i].length != 0)
2518 fprintf (e, " %lu, \"", offset + i);
2519 unicode_print (e, stringtable->strings[i].string,
2520 stringtable->strings[i].length);
2521 fprintf (e, "\"\n");
2525 fprintf (e, "END\n");
2528 /* Write out a versioninfo resource. */
2530 static void
2531 write_rc_versioninfo (e, versioninfo)
2532 FILE *e;
2533 const struct versioninfo *versioninfo;
2535 const struct fixed_versioninfo *f;
2536 const struct ver_info *vi;
2538 f = versioninfo->fixed;
2539 if (f->file_version_ms != 0 || f->file_version_ls != 0)
2540 fprintf (e, " FILEVERSION %lu, %lu, %lu, %lu\n",
2541 (f->file_version_ms >> 16) & 0xffff,
2542 f->file_version_ms & 0xffff,
2543 (f->file_version_ls >> 16) & 0xffff,
2544 f->file_version_ls & 0xffff);
2545 if (f->product_version_ms != 0 || f->product_version_ls != 0)
2546 fprintf (e, " PRODUCTVERSION %lu, %lu, %lu, %lu\n",
2547 (f->product_version_ms >> 16) & 0xffff,
2548 f->product_version_ms & 0xffff,
2549 (f->product_version_ls >> 16) & 0xffff,
2550 f->product_version_ls & 0xffff);
2551 if (f->file_flags_mask != 0)
2552 fprintf (e, " FILEFLAGSMASK 0x%lx\n", f->file_flags_mask);
2553 if (f->file_flags != 0)
2554 fprintf (e, " FILEFLAGS 0x%lx\n", f->file_flags);
2555 if (f->file_os != 0)
2556 fprintf (e, " FILEOS 0x%lx\n", f->file_os);
2557 if (f->file_type != 0)
2558 fprintf (e, " FILETYPE 0x%lx\n", f->file_type);
2559 if (f->file_subtype != 0)
2560 fprintf (e, " FILESUBTYPE 0x%lx\n", f->file_subtype);
2561 if (f->file_date_ms != 0 || f->file_date_ls != 0)
2562 fprintf (e, "// Date: %lu, %lu\n", f->file_date_ms, f->file_date_ls);
2564 fprintf (e, "BEGIN\n");
2566 for (vi = versioninfo->var; vi != NULL; vi = vi->next)
2568 switch (vi->type)
2570 case VERINFO_STRING:
2572 const struct ver_stringinfo *vs;
2574 fprintf (e, " BLOCK \"StringFileInfo\"\n");
2575 fprintf (e, " BEGIN\n");
2576 fprintf (e, " BLOCK \"");
2577 unicode_print (e, vi->u.string.language, -1);
2578 fprintf (e, "\"\n");
2579 fprintf (e, " BEGIN\n");
2581 for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
2583 fprintf (e, " VALUE \"");
2584 unicode_print (e, vs->key, -1);
2585 fprintf (e, "\", \"");
2586 unicode_print (e, vs->value, -1);
2587 fprintf (e, "\"\n");
2590 fprintf (e, " END\n");
2591 fprintf (e, " END\n");
2592 break;
2595 case VERINFO_VAR:
2597 const struct ver_varinfo *vv;
2599 fprintf (e, " BLOCK \"VarFileInfo\"\n");
2600 fprintf (e, " BEGIN\n");
2601 fprintf (e, " VALUE \"");
2602 unicode_print (e, vi->u.var.key, -1);
2603 fprintf (e, "\"");
2605 for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
2606 fprintf (e, ", 0x%x, %d", (unsigned int) vv->language,
2607 vv->charset);
2609 fprintf (e, "\n END\n");
2611 break;
2616 fprintf (e, "END\n");
2619 /* Write out data which would normally be read from a file. */
2621 static void
2622 write_rc_filedata (e, length, data)
2623 FILE *e;
2624 unsigned long length;
2625 const unsigned char *data;
2627 unsigned long i;
2629 for (i = 0; i + 15 < length; i += 16)
2631 fprintf (e, "// %4lx: ", i);
2632 fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x ",
2633 data[i + 0], data[i + 1], data[i + 2], data[i + 3],
2634 data[i + 4], data[i + 5], data[i + 6], data[i + 7]);
2635 fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
2636 data[i + 8], data[i + 9], data[i + 10], data[i + 11],
2637 data[i + 12], data[i + 13], data[i + 14], data[i + 15]);
2640 if (i < length)
2642 fprintf (e, "// %4lx:", i);
2643 while (i < length)
2645 fprintf (e, " %02x", data[i]);
2646 ++i;
2648 fprintf (e, "\n");