1 /* resrc.c -- read and write Windows rc files.
2 Copyright 1997 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
22 /* This file contains function that read and write Windows rc files.
23 These are text files that represent resources. */
27 #include "libiberty.h"
34 /* The default preprocessor. */
36 #define DEFAULT_PREPROCESSOR "gcc -E -xc-header -DRC_INVOKED"
38 /* We read the directory entries in a cursor or icon file into
39 instances of this structure. */
45 /* Height of image. */
47 /* Number of colors in image. */
48 unsigned char colorcount;
54 unsigned short planes;
60 /* X coordinate of hotspot. */
61 unsigned short xhotspot;
62 /* Y coordinate of hotspot. */
63 unsigned short yhotspot;
68 /* File offset of image. */
72 /* The name of the rc file we are reading. */
76 /* The line number in the rc file. */
80 /* The pipe we are reading from, so that we can close it if we exit. */
82 static FILE *cpp_pipe;
84 /* As we read the rc file, we attach information to this structure. */
86 static struct res_directory *resources;
88 /* The number of cursor resources we have written out. */
92 /* The number of font resources we have written out. */
96 /* Font directory information. */
98 struct fontdir *fontdirs;
100 /* Resource info to use for fontdirs. */
102 struct res_res_info fontdirs_resinfo;
104 /* The number of icon resources we have written out. */
108 /* Local functions. */
110 static void close_pipe PARAMS ((void));
111 static void unexpected_eof PARAMS ((const char *));
112 static int get_word PARAMS ((FILE *, const char *));
113 static unsigned long get_long PARAMS ((FILE *, const char *));
115 PARAMS ((FILE *, unsigned char *, unsigned long, const char *));
116 static void define_fontdirs PARAMS ((void));
118 /* Read an rc file. */
120 struct res_directory *
121 read_rc_file (filename, preprocessor, preprocargs, language)
122 const char *filename;
123 const char *preprocessor;
124 const char *preprocargs;
129 if (preprocessor == NULL)
130 preprocessor = DEFAULT_PREPROCESSOR;
132 if (preprocargs == NULL)
134 if (filename == NULL)
137 cmd = xmalloc (strlen (preprocessor)
138 + strlen (preprocargs)
141 sprintf (cmd, "%s %s %s", preprocessor, preprocargs, filename);
143 cpp_pipe = popen (cmd, FOPEN_RT);
144 if (cpp_pipe == NULL)
145 fatal ("can't popen `%s': %s", cmd, strerror (errno));
148 xatexit (close_pipe);
150 rc_filename = xstrdup (filename);
153 rcparse_set_language (language);
157 if (pclose (cpp_pipe) != 0)
158 fprintf (stderr, "%s: warning: preprocessor failed\n", program_name);
161 if (fontdirs != NULL)
170 /* Close the pipe if it is open. This is called via xatexit. */
175 if (cpp_pipe != NULL)
179 /* Report an error while reading an rc file. */
185 fatal ("%s:%d: %s", rc_filename, rc_lineno, msg);
188 /* Issue a warning while reading an rc file. */
191 rcparse_warning (msg)
194 fprintf (stderr, "%s:%d: %s\n", rc_filename, rc_lineno, msg);
197 /* Die if we get an unexpected end of file. */
203 fatal ("%s: unexpected EOF", msg);
206 /* Read a 16 bit word from a file. The data is assumed to be little
219 unexpected_eof (msg);
220 return ((b2 & 0xff) << 8) | (b1 & 0xff);
223 /* Read a 32 bit word from a file. The data is assumed to be little
238 unexpected_eof (msg);
239 return (((((((b4 & 0xff) << 8)
245 /* Read data from a file. This is a wrapper to do error checking. */
248 get_data (e, p, c, msg)
256 got = fread (p, 1, c, e);
260 fatal ("%s: read of %lu returned %lu", msg, c, got);
263 /* Define an accelerator resource. */
266 define_accelerator (id, resinfo, data)
268 const struct res_res_info *resinfo;
269 struct accelerator *data;
271 struct res_resource *r;
273 r = define_standard_resource (&resources, RT_ACCELERATORS, id,
274 resinfo->language, 0);
275 r->type = RES_TYPE_ACCELERATOR;
277 r->res_info = *resinfo;
280 /* Define a bitmap resource. Bitmap data is stored in a file. The
281 first 14 bytes of the file are a standard header, which is not
282 included in the resource data. */
284 #define BITMAP_SKIP (14)
287 define_bitmap (id, resinfo, filename)
289 const struct res_res_info *resinfo;
290 const char *filename;
297 struct res_resource *r;
299 e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename);
301 if (stat (real_filename, &s) < 0)
302 fatal ("stat failed on bitmap file `%s': %s", real_filename,
305 data = (unsigned char *) res_alloc (s.st_size - BITMAP_SKIP);
307 for (i = 0; i < BITMAP_SKIP; i++)
310 get_data (e, data, s.st_size - BITMAP_SKIP, real_filename);
313 free (real_filename);
315 r = define_standard_resource (&resources, RT_BITMAP, id,
316 resinfo->language, 0);
318 r->type = RES_TYPE_BITMAP;
319 r->u.data.length = s.st_size - BITMAP_SKIP;
320 r->u.data.data = data;
321 r->res_info = *resinfo;
324 /* Define a cursor resource. A cursor file may contain a set of
325 bitmaps, each representing the same cursor at various different
326 resolutions. They each get written out with a different ID. The
327 real cursor resource is then a group resource which can be used to
328 select one of the actual cursors. */
331 define_cursor (id, resinfo, filename)
333 const struct res_res_info *resinfo;
334 const char *filename;
339 struct icondir *icondirs;
341 struct res_resource *r;
342 struct group_cursor *first, **pp;
344 e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename);
346 /* A cursor file is basically an icon file. The start of the file
347 is a three word structure. The first word is ignored. The
348 second word is the type of data. The third word is the number of
351 get_word (e, real_filename);
352 type = get_word (e, real_filename);
353 count = get_word (e, real_filename);
355 fatal ("cursor file `%s' does not contain cursor data", real_filename);
357 /* Read in the icon directory entries. */
359 icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
361 for (i = 0; i < count; i++)
363 icondirs[i].width = getc (e);
364 icondirs[i].height = getc (e);
365 icondirs[i].colorcount = getc (e);
367 icondirs[i].u.cursor.xhotspot = get_word (e, real_filename);
368 icondirs[i].u.cursor.yhotspot = get_word (e, real_filename);
369 icondirs[i].bytes = get_long (e, real_filename);
370 icondirs[i].offset = get_long (e, real_filename);
373 unexpected_eof (real_filename);
376 /* Define each cursor as a unique resource. */
378 first_cursor = cursors;
380 for (i = 0; i < count; i++)
386 if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
387 fatal ("%s: fseek to %lu failed: %s", real_filename,
388 icondirs[i].offset, strerror (errno));
390 data = (unsigned char *) res_alloc (icondirs[i].bytes);
392 get_data (e, data, icondirs[i].bytes, real_filename);
394 c = (struct cursor *) res_alloc (sizeof *c);
395 c->xhotspot = icondirs[i].u.cursor.xhotspot;
396 c->yhotspot = icondirs[i].u.cursor.yhotspot;
397 c->length = icondirs[i].bytes;
405 r = define_standard_resource (&resources, RT_CURSOR, name,
406 resinfo->language, 0);
407 r->type = RES_TYPE_CURSOR;
409 r->res_info = *resinfo;
413 free (real_filename);
415 /* Define a cursor group resource. */
419 for (i = 0; i < count; i++)
421 struct group_cursor *cg;
423 cg = (struct group_cursor *) res_alloc (sizeof *cg);
425 cg->width = icondirs[i].width;
426 cg->height = 2 * icondirs[i].height;
428 /* FIXME: What should these be set to? */
432 cg->bytes = icondirs[i].bytes + 4;
433 cg->index = first_cursor + i + 1;
441 r = define_standard_resource (&resources, RT_GROUP_CURSOR, id,
442 resinfo->language, 0);
443 r->type = RES_TYPE_GROUP_CURSOR;
444 r->u.group_cursor = first;
445 r->res_info = *resinfo;
448 /* Define a dialog resource. */
451 define_dialog (id, resinfo, dialog)
453 const struct res_res_info *resinfo;
454 const struct dialog *dialog;
457 struct res_resource *r;
459 copy = (struct dialog *) res_alloc (sizeof *copy);
462 r = define_standard_resource (&resources, RT_DIALOG, id,
463 resinfo->language, 0);
464 r->type = RES_TYPE_DIALOG;
466 r->res_info = *resinfo;
469 /* Define a dialog control. This does not define a resource, but
470 merely allocates and fills in a structure. */
472 struct dialog_control *
473 define_control (text, id, x, y, width, height, class, style, exstyle)
479 unsigned long height;
482 unsigned long exstyle;
484 struct dialog_control *n;
486 n = (struct dialog_control *) res_alloc (sizeof *n);
490 n->exstyle = exstyle;
496 n->class.u.id = class;
498 res_string_to_id (&n->text, text);
510 /* Define a font resource. */
513 define_font (id, resinfo, filename)
515 const struct res_res_info *resinfo;
516 const char *filename;
522 struct res_resource *r;
525 unsigned char *fontdata;
527 const char *device, *face;
530 e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
532 if (stat (real_filename, &s) < 0)
533 fatal ("stat failed on bitmap file `%s': %s", real_filename,
536 data = (unsigned char *) res_alloc (s.st_size);
538 get_data (e, data, s.st_size, real_filename);
541 free (real_filename);
543 r = define_standard_resource (&resources, RT_FONT, id,
544 resinfo->language, 0);
546 r->type = RES_TYPE_FONT;
547 r->u.data.length = s.st_size;
548 r->u.data.data = data;
549 r->res_info = *resinfo;
551 /* For each font resource, we must add an entry in the FONTDIR
552 resource. The FONTDIR resource includes some strings in the font
553 file. To find them, we have to do some magic on the data we have
556 offset = ((((((data[47] << 8)
560 if (offset > 0 && offset < s.st_size)
561 device = (char *) data + offset;
565 offset = ((((((data[51] << 8)
569 if (offset > 0 && offset < s.st_size)
570 face = (char *) data + offset;
576 fontdatalength = 58 + strlen (device) + strlen (face);
577 fontdata = (unsigned char *) res_alloc (fontdatalength);
578 memcpy (fontdata, data, 56);
579 strcpy ((char *) fontdata + 56, device);
580 strcpy ((char *) fontdata + 57 + strlen (device), face);
582 fd = (struct fontdir *) res_alloc (sizeof *fd);
585 fd->length = fontdatalength;
588 for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next)
592 /* For the single fontdirs resource, we always use the resource
593 information of the last font. I don't know what else to do. */
594 fontdirs_resinfo = *resinfo;
597 /* Define the fontdirs resource. This is called after the entire rc
598 file has been parsed, if any font resources were seen. */
603 struct res_resource *r;
609 r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
611 r->type = RES_TYPE_FONTDIR;
612 r->u.fontdir = fontdirs;
613 r->res_info = fontdirs_resinfo;
616 /* Define an icon resource. An icon file may contain a set of
617 bitmaps, each representing the same icon at various different
618 resolutions. They each get written out with a different ID. The
619 real icon resource is then a group resource which can be used to
620 select one of the actual icon bitmaps. */
623 define_icon (id, resinfo, filename)
625 const struct res_res_info *resinfo;
626 const char *filename;
631 struct icondir *icondirs;
633 struct res_resource *r;
634 struct group_icon *first, **pp;
636 e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename);
638 /* The start of an icon file is a three word structure. The first
639 word is ignored. The second word is the type of data. The third
640 word is the number of entries. */
642 get_word (e, real_filename);
643 type = get_word (e, real_filename);
644 count = get_word (e, real_filename);
646 fatal ("icon file `%s' does not contain icon data", real_filename);
648 /* Read in the icon directory entries. */
650 icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
652 for (i = 0; i < count; i++)
654 icondirs[i].width = getc (e);
655 icondirs[i].height = getc (e);
656 icondirs[i].colorcount = getc (e);
658 icondirs[i].u.icon.planes = get_word (e, real_filename);
659 icondirs[i].u.icon.bits = get_word (e, real_filename);
660 icondirs[i].bytes = get_long (e, real_filename);
661 icondirs[i].offset = get_long (e, real_filename);
664 unexpected_eof (real_filename);
667 /* Define each icon as a unique resource. */
671 for (i = 0; i < count; i++)
676 if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
677 fatal ("%s: fseek to %lu failed: %s", real_filename,
678 icondirs[i].offset, strerror (errno));
680 data = (unsigned char *) res_alloc (icondirs[i].bytes);
682 get_data (e, data, icondirs[i].bytes, real_filename);
689 r = define_standard_resource (&resources, RT_ICON, name,
690 resinfo->language, 0);
691 r->type = RES_TYPE_ICON;
692 r->u.data.length = icondirs[i].bytes;
693 r->u.data.data = data;
694 r->res_info = *resinfo;
698 free (real_filename);
700 /* Define an icon group resource. */
704 for (i = 0; i < count; i++)
706 struct group_icon *cg;
708 /* For some reason, at least in some files the planes and bits
709 are zero. We instead set them from the color. This is
712 cg = (struct group_icon *) res_alloc (sizeof *cg);
714 cg->width = icondirs[i].width;
715 cg->height = icondirs[i].height;
716 cg->colors = icondirs[i].colorcount;
720 while ((1 << cg->bits) < cg->colors)
723 cg->bytes = icondirs[i].bytes;
724 cg->index = first_icon + i + 1;
732 r = define_standard_resource (&resources, RT_GROUP_ICON, id,
733 resinfo->language, 0);
734 r->type = RES_TYPE_GROUP_ICON;
735 r->u.group_icon = first;
736 r->res_info = *resinfo;
739 /* Define a menu resource. */
742 define_menu (id, resinfo, menuitems)
744 const struct res_res_info *resinfo;
745 struct menuitem *menuitems;
748 struct res_resource *r;
750 m = (struct menu *) res_alloc (sizeof *m);
751 m->items = menuitems;
754 r = define_standard_resource (&resources, RT_MENU, id, resinfo->language, 0);
755 r->type = RES_TYPE_MENU;
757 r->res_info = *resinfo;
760 /* Define a menu item. This does not define a resource, but merely
761 allocates and fills in a structure. */
764 define_menuitem (text, menuid, type, state, help, menuitems)
770 struct menuitem *menuitems;
774 mi = (struct menuitem *) res_alloc (sizeof *mi);
782 unicode_from_ascii ((int *) NULL, &mi->text, text);
784 mi->popup = menuitems;
788 /* Define a messagetable resource. */
791 define_messagetable (id, resinfo, filename)
793 const struct res_res_info *resinfo;
794 const char *filename;
800 struct res_resource *r;
802 e = open_file_search (filename, FOPEN_RB, "messagetable file",
805 if (stat (real_filename, &s) < 0)
806 fatal ("stat failed on bitmap file `%s': %s", real_filename,
809 data = (unsigned char *) res_alloc (s.st_size);
811 get_data (e, data, s.st_size, real_filename);
814 free (real_filename);
816 r = define_standard_resource (&resources, RT_MESSAGETABLE, id,
817 resinfo->language, 0);
819 r->type = RES_TYPE_MESSAGETABLE;
820 r->u.data.length = s.st_size;
821 r->u.data.data = data;
822 r->res_info = *resinfo;
825 /* Define an rcdata resource. */
828 define_rcdata (id, resinfo, data)
830 const struct res_res_info *resinfo;
831 struct rcdata_item *data;
833 struct res_resource *r;
835 r = define_standard_resource (&resources, RT_RCDATA, id,
836 resinfo->language, 0);
837 r->type = RES_TYPE_RCDATA;
839 r->res_info = *resinfo;
842 /* Create an rcdata item holding a string. */
845 define_rcdata_string (string, len)
849 struct rcdata_item *ri;
852 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
854 ri->type = RCDATA_STRING;
855 ri->u.string.length = len;
856 s = (char *) res_alloc (len);
857 memcpy (s, string, len);
863 /* Create an rcdata item holding a number. */
866 define_rcdata_number (val, dword)
870 struct rcdata_item *ri;
872 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
874 ri->type = dword ? RCDATA_DWORD : RCDATA_WORD;
880 /* Define a stringtable resource. This is called for each string
881 which appears in a STRINGTABLE statement. */
884 define_stringtable (resinfo, stringid, string)
885 const struct res_res_info *resinfo;
886 unsigned long stringid;
890 struct res_resource *r;
893 id.u.id = stringid >> 4;
894 r = define_standard_resource (&resources, RT_STRING, id,
895 resinfo->language, 1);
897 if (r->type == RES_TYPE_UNINITIALIZED)
901 r->type = RES_TYPE_STRINGTABLE;
902 r->u.stringtable = ((struct stringtable *)
903 res_alloc (sizeof (struct stringtable)));
904 for (i = 0; i < 16; i++)
906 r->u.stringtable->strings[i].length = 0;
907 r->u.stringtable->strings[i].string = NULL;
910 r->res_info = *resinfo;
913 unicode_from_ascii (&r->u.stringtable->strings[stringid & 0xf].length,
914 &r->u.stringtable->strings[stringid & 0xf].string,
918 /* Define a user data resource where the data is in the rc file. */
921 define_user_data (id, type, resinfo, data)
924 const struct res_res_info *resinfo;
925 struct rcdata_item *data;
927 struct res_id ids[3];
928 struct res_resource *r;
933 ids[2].u.id = resinfo->language;
935 r = define_resource (&resources, 3, ids, 0);
936 r->type = RES_TYPE_USERDATA;
937 r->u.userdata = data;
938 r->res_info = *resinfo;
941 /* Define a user data resource where the data is in a file. */
944 define_user_file (id, type, resinfo, filename)
947 const struct res_res_info *resinfo;
948 const char *filename;
954 struct res_id ids[3];
955 struct res_resource *r;
957 e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
959 if (stat (real_filename, &s) < 0)
960 fatal ("stat failed on bitmap file `%s': %s", real_filename,
963 data = (unsigned char *) res_alloc (s.st_size);
965 get_data (e, data, s.st_size, real_filename);
968 free (real_filename);
973 ids[2].u.id = resinfo->language;
975 r = define_resource (&resources, 3, ids, 0);
976 r->type = RES_TYPE_USERDATA;
977 r->u.userdata = ((struct rcdata_item *)
978 res_alloc (sizeof (struct rcdata_item)));
979 r->u.userdata->next = NULL;
980 r->u.userdata->type = RCDATA_BUFFER;
981 r->u.userdata->u.buffer.length = s.st_size;
982 r->u.userdata->u.buffer.data = data;
983 r->res_info = *resinfo;
986 /* Define a versioninfo resource. */
989 define_versioninfo (id, language, fixedverinfo, verinfo)
992 struct fixed_versioninfo *fixedverinfo;
993 struct ver_info *verinfo;
995 struct res_resource *r;
997 r = define_standard_resource (&resources, RT_VERSION, id, language, 0);
998 r->type = RES_TYPE_VERSIONINFO;
999 r->u.versioninfo = ((struct versioninfo *)
1000 res_alloc (sizeof (struct versioninfo)));
1001 r->u.versioninfo->fixed = fixedverinfo;
1002 r->u.versioninfo->var = verinfo;
1003 r->res_info.language = language;
1006 /* Add string version info to a list of version information. */
1009 append_ver_stringfileinfo (verinfo, language, strings)
1010 struct ver_info *verinfo;
1011 const char *language;
1012 struct ver_stringinfo *strings;
1014 struct ver_info *vi, **pp;
1016 vi = (struct ver_info *) res_alloc (sizeof *vi);
1018 vi->type = VERINFO_STRING;
1019 unicode_from_ascii ((int *) NULL, &vi->u.string.language, language);
1020 vi->u.string.strings = strings;
1022 for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1029 /* Add variable version info to a list of version information. */
1032 append_ver_varfileinfo (verinfo, key, var)
1033 struct ver_info *verinfo;
1035 struct ver_varinfo *var;
1037 struct ver_info *vi, **pp;
1039 vi = (struct ver_info *) res_alloc (sizeof *vi);
1041 vi->type = VERINFO_VAR;
1042 unicode_from_ascii ((int *) NULL, &vi->u.var.key, key);
1043 vi->u.var.var = var;
1045 for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1052 /* Append version string information to a list. */
1054 struct ver_stringinfo *
1055 append_verval (strings, key, value)
1056 struct ver_stringinfo *strings;
1060 struct ver_stringinfo *vs, **pp;
1062 vs = (struct ver_stringinfo *) res_alloc (sizeof *vs);
1064 unicode_from_ascii ((int *) NULL, &vs->key, key);
1065 unicode_from_ascii ((int *) NULL, &vs->value, value);
1067 for (pp = &strings; *pp != NULL; pp = &(*pp)->next)
1074 /* Append version variable information to a list. */
1076 struct ver_varinfo *
1077 append_vertrans (var, language, charset)
1078 struct ver_varinfo *var;
1079 unsigned long language;
1080 unsigned long charset;
1082 struct ver_varinfo *vv, **pp;
1084 vv = (struct ver_varinfo *) res_alloc (sizeof *vv);
1086 vv->language = language;
1087 vv->charset = charset;
1089 for (pp = &var; *pp != NULL; pp = &(*pp)->next)
1096 /* Local functions used to write out an rc file. */
1098 static void indent PARAMS ((FILE *, int));
1099 static void write_rc_directory
1100 PARAMS ((FILE *, const struct res_directory *, const struct res_id *,
1101 const struct res_id *, int *, int));
1102 static void write_rc_subdir
1103 PARAMS ((FILE *, const struct res_entry *, const struct res_id *,
1104 const struct res_id *, int *, int));
1105 static void write_rc_resource
1106 PARAMS ((FILE *, const struct res_id *, const struct res_id *,
1107 const struct res_resource *, int *));
1108 static void write_rc_accelerators
1109 PARAMS ((FILE *, const struct accelerator *));
1110 static void write_rc_cursor PARAMS ((FILE *, const struct cursor *));
1111 static void write_rc_group_cursor
1112 PARAMS ((FILE *, const struct group_cursor *));
1113 static void write_rc_dialog PARAMS ((FILE *, const struct dialog *));
1114 static void write_rc_dialog_control
1115 PARAMS ((FILE *, const struct dialog_control *));
1116 static void write_rc_fontdir PARAMS ((FILE *, const struct fontdir *));
1117 static void write_rc_group_icon PARAMS ((FILE *, const struct group_icon *));
1118 static void write_rc_menu PARAMS ((FILE *, const struct menu *, int));
1119 static void write_rc_menuitems
1120 PARAMS ((FILE *, const struct menuitem *, int, int));
1121 static void write_rc_rcdata PARAMS ((FILE *, const struct rcdata_item *, int));
1122 static void write_rc_stringtable
1123 PARAMS ((FILE *, const struct res_id *, const struct stringtable *));
1124 static void write_rc_versioninfo PARAMS ((FILE *, const struct versioninfo *));
1125 static void write_rc_filedata
1126 PARAMS ((FILE *, unsigned long, const unsigned char *));
1128 /* Indent a given number of spaces. */
1137 for (i = 0; i < c; i++)
1141 /* Dump the resources we have read in the format of an rc file.
1143 Actually, we don't use the format of an rc file, because it's way
1144 too much of a pain--for example, we'd have to write icon resources
1145 into a file and refer to that file. We just generate a readable
1146 format that kind of looks like an rc file, and is useful for
1147 understanding the contents of a resource file. Someday we may want
1148 to generate an rc file which the rc compiler can read; if that day
1149 comes, this code will have to be fixed up. */
1152 write_rc_file (filename, resources)
1153 const char *filename;
1154 const struct res_directory *resources;
1159 if (filename == NULL)
1163 e = fopen (filename, FOPEN_WT);
1165 fatal ("can't open `%s' for output: %s", filename, strerror (errno));
1169 write_rc_directory (e, resources, (const struct res_id *) NULL,
1170 (const struct res_id *) NULL, &language, 1);
1173 /* Write out a directory. E is the file to write to. RD is the
1174 directory. TYPE is a pointer to the level 1 ID which serves as the
1175 resource type. NAME is a pointer to the level 2 ID which serves as
1176 an individual resource name. LANGUAGE is a pointer to the current
1177 language. LEVEL is the level in the tree. */
1180 write_rc_directory (e, rd, type, name, language, level)
1182 const struct res_directory *rd;
1183 const struct res_id *type;
1184 const struct res_id *name;
1188 const struct res_entry *re;
1190 /* Print out some COFF information that rc files can't represent. */
1193 fprintf (e, "// Time stamp: %lu\n", rd->time);
1194 if (rd->characteristics != 0)
1195 fprintf (e, "// Characteristics: %lu\n", rd->characteristics);
1196 if (rd->major != 0 || rd->minor != 0)
1197 fprintf (e, "// Version: %d %d\n", rd->major, rd->minor);
1199 for (re = rd->entries; re != NULL; re = re->next)
1204 /* If we're at level 1, the key of this resource is the
1205 type. This normally duplicates the information we have
1206 stored with the resource itself, but we need to remember
1207 the type if this is a user define resource type. */
1212 /* If we're at level 2, the key of this resource is the name
1213 we are going to use in the rc printout. */
1218 /* If we're at level 3, then this key represents a language.
1219 Use it to update the current language. */
1221 && re->id.u.id != *language
1222 && (re->id.u.id & 0xffff) == re->id.u.id)
1224 fprintf (e, "LANGUAGE %lu, %lu\n",
1225 re->id.u.id & 0xff, (re->id.u.id >> 8) & 0xff);
1226 *language = re->id.u.id;
1235 write_rc_subdir (e, re, type, name, language, level);
1240 /* This is the normal case: the three levels are
1241 TYPE/NAME/LANGUAGE. NAME will have been set at level
1242 2, and represents the name to use. We probably just
1243 set LANGUAGE, and it will probably match what the
1244 resource itself records if anything. */
1245 write_rc_resource (e, type, name, re->u.res, language);
1249 fprintf (e, "// Resource at unexpected level %d\n", level);
1250 write_rc_resource (e, type, (struct res_id *) NULL, re->u.res,
1257 /* Write out a subdirectory entry. E is the file to write to. RE is
1258 the subdirectory entry. TYPE and NAME are pointers to higher level
1259 IDs, or NULL. LANGUAGE is a pointer to the current language.
1260 LEVEL is the level in the tree. */
1263 write_rc_subdir (e, re, type, name, language, level)
1265 const struct res_entry *re;
1266 const struct res_id *type;
1267 const struct res_id *name;
1275 fprintf (e, "// Type: ");
1277 res_id_print (e, re->id, 1);
1282 switch (re->id.u.id)
1284 case RT_CURSOR: s = "cursor"; break;
1285 case RT_BITMAP: s = "bitmap"; break;
1286 case RT_ICON: s = "icon"; break;
1287 case RT_MENU: s = "menu"; break;
1288 case RT_DIALOG: s = "dialog"; break;
1289 case RT_STRING: s = "stringtable"; break;
1290 case RT_FONTDIR: s = "fontdir"; break;
1291 case RT_FONT: s = "font"; break;
1292 case RT_ACCELERATORS: s = "accelerators"; break;
1293 case RT_RCDATA: s = "rcdata"; break;
1294 case RT_MESSAGETABLE: s = "messagetable"; break;
1295 case RT_GROUP_CURSOR: s = "group cursor"; break;
1296 case RT_GROUP_ICON: s = "group icon"; break;
1297 case RT_VERSION: s = "version"; break;
1298 case RT_DLGINCLUDE: s = "dlginclude"; break;
1299 case RT_PLUGPLAY: s = "plugplay"; break;
1300 case RT_VXD: s = "vxd"; break;
1301 case RT_ANICURSOR: s = "anicursor"; break;
1302 case RT_ANIICON: s = "aniicon"; break;
1303 default: s = NULL; break;
1307 fprintf (e, "%s", s);
1309 res_id_print (e, re->id, 1);
1315 fprintf (e, "// Name: ");
1316 res_id_print (e, re->id, 1);
1321 fprintf (e, "// Language: ");
1322 res_id_print (e, re->id, 1);
1327 fprintf (e, "// Level %d: ", level);
1328 res_id_print (e, re->id, 1);
1332 write_rc_directory (e, re->u.dir, type, name, language, level + 1);
1335 /* Write out a single resource. E is the file to write to. TYPE is a
1336 pointer to the type of the resource. NAME is a pointer to the name
1337 of the resource; it will be NULL if there is a level mismatch. RES
1338 is the resource data. LANGUAGE is a pointer to the current
1342 write_rc_resource (e, type, name, res, language)
1344 const struct res_id *type;
1345 const struct res_id *name;
1346 const struct res_resource *res;
1360 case RES_TYPE_ACCELERATOR:
1362 rt = RT_ACCELERATORS;
1365 case RES_TYPE_BITMAP:
1370 case RES_TYPE_CURSOR:
1375 case RES_TYPE_GROUP_CURSOR:
1377 rt = RT_GROUP_CURSOR;
1380 case RES_TYPE_DIALOG:
1381 if (extended_dialog (res->u.dialog))
1393 case RES_TYPE_FONTDIR:
1403 case RES_TYPE_GROUP_ICON:
1409 if (extended_menu (res->u.menu))
1422 case RES_TYPE_MESSAGETABLE:
1424 rt = RT_MESSAGETABLE;
1427 case RES_TYPE_RCDATA:
1432 case RES_TYPE_STRINGTABLE:
1437 case RES_TYPE_USERDATA:
1442 case RES_TYPE_VERSIONINFO:
1450 && (type->named || type->u.id != rt))
1452 fprintf (e, "// Unexpected resource type mismatch: ");
1453 res_id_print (e, *type, 1);
1454 fprintf (e, " != %d", rt);
1457 if (res->coff_info.codepage != 0)
1458 fprintf (e, "// Code page: %lu\n", res->coff_info.codepage);
1459 if (res->coff_info.reserved != 0)
1460 fprintf (e, "// COFF reserved value: %lu\n", res->coff_info.reserved);
1463 res_id_print (e, *name, 0);
1465 fprintf (e, "??Unknown-Name??");
1469 fprintf (e, "%s", s);
1470 else if (type != NULL)
1471 res_id_print (e, *type, 0);
1473 fprintf (e, "??Unknown-Type??");
1475 if (res->res_info.memflags != 0)
1477 if ((res->res_info.memflags & MEMFLAG_MOVEABLE) != 0)
1478 fprintf (e, " MOVEABLE");
1479 if ((res->res_info.memflags & MEMFLAG_PURE) != 0)
1480 fprintf (e, " PURE");
1481 if ((res->res_info.memflags & MEMFLAG_PRELOAD) != 0)
1482 fprintf (e, " PRELOAD");
1483 if ((res->res_info.memflags & MEMFLAG_DISCARDABLE) != 0)
1484 fprintf (e, " DISCARDABLE");
1487 if (res->type == RES_TYPE_DIALOG)
1489 fprintf (e, " %d, %d, %d, %d", res->u.dialog->x, res->u.dialog->y,
1490 res->u.dialog->width, res->u.dialog->height);
1491 if (res->u.dialog->ex != NULL
1492 && res->u.dialog->ex->help != 0)
1493 fprintf (e, ", %lu", res->u.dialog->ex->help);
1498 if ((res->res_info.language != 0 && res->res_info.language != *language)
1499 || res->res_info.characteristics != 0
1500 || res->res_info.version != 0)
1506 case RES_TYPE_ACCELERATOR:
1507 case RES_TYPE_DIALOG:
1509 case RES_TYPE_RCDATA:
1510 case RES_TYPE_STRINGTABLE:
1519 if (res->res_info.language != 0 && res->res_info.language != *language)
1520 fprintf (e, "%sLANGUAGE %d, %d\n",
1521 modifiers ? "// " : "",
1522 res->res_info.language & 0xff,
1523 (res->res_info.language >> 8) & 0xff);
1524 if (res->res_info.characteristics != 0)
1525 fprintf (e, "%sCHARACTERISTICS %lu\n",
1526 modifiers ? "// " : "",
1527 res->res_info.characteristics);
1528 if (res->res_info.version != 0)
1529 fprintf (e, "%sVERSION %lu\n",
1530 modifiers ? "// " : "",
1531 res->res_info.version);
1539 case RES_TYPE_ACCELERATOR:
1540 write_rc_accelerators (e, res->u.acc);
1543 case RES_TYPE_CURSOR:
1544 write_rc_cursor (e, res->u.cursor);
1547 case RES_TYPE_GROUP_CURSOR:
1548 write_rc_group_cursor (e, res->u.group_cursor);
1551 case RES_TYPE_DIALOG:
1552 write_rc_dialog (e, res->u.dialog);
1555 case RES_TYPE_FONTDIR:
1556 write_rc_fontdir (e, res->u.fontdir);
1559 case RES_TYPE_GROUP_ICON:
1560 write_rc_group_icon (e, res->u.group_icon);
1564 write_rc_menu (e, res->u.menu, menuex);
1567 case RES_TYPE_RCDATA:
1568 write_rc_rcdata (e, res->u.rcdata, 0);
1571 case RES_TYPE_STRINGTABLE:
1572 write_rc_stringtable (e, name, res->u.stringtable);
1575 case RES_TYPE_USERDATA:
1576 write_rc_rcdata (e, res->u.userdata, 0);
1579 case RES_TYPE_VERSIONINFO:
1580 write_rc_versioninfo (e, res->u.versioninfo);
1583 case RES_TYPE_BITMAP:
1586 case RES_TYPE_MESSAGETABLE:
1587 write_rc_filedata (e, res->u.data.length, res->u.data.data);
1592 /* Write out accelerator information. */
1595 write_rc_accelerators (e, accelerators)
1597 const struct accelerator *accelerators;
1599 const struct accelerator *acc;
1601 fprintf (e, "BEGIN\n");
1602 for (acc = accelerators; acc != NULL; acc = acc->next)
1608 if ((acc->key & 0x7f) == acc->key
1609 && isprint ((unsigned char) acc->key)
1610 && (acc->flags & ACC_VIRTKEY) == 0)
1612 fprintf (e, "\"%c\"", acc->key);
1617 fprintf (e, "%d", acc->key);
1621 fprintf (e, ", %d", acc->id);
1625 if ((acc->flags & ACC_VIRTKEY) != 0)
1626 fprintf (e, ", VIRTKEY");
1628 fprintf (e, ", ASCII");
1631 if ((acc->flags & ACC_SHIFT) != 0)
1632 fprintf (e, ", SHIFT");
1633 if ((acc->flags & ACC_CONTROL) != 0)
1634 fprintf (e, ", CONTROL");
1635 if ((acc->flags & ACC_ALT) != 0)
1636 fprintf (e, ", ALT");
1641 fprintf (e, "END\n");
1644 /* Write out cursor information. This would normally be in a separate
1645 file, which the rc file would include. */
1648 write_rc_cursor (e, cursor)
1650 const struct cursor *cursor;
1652 fprintf (e, "// Hotspot: x: %d; y: %d\n", cursor->xhotspot,
1654 write_rc_filedata (e, cursor->length, cursor->data);
1657 /* Write out group cursor data. This would normally be built from the
1661 write_rc_group_cursor (e, group_cursor)
1663 const struct group_cursor *group_cursor;
1665 const struct group_cursor *gc;
1667 for (gc = group_cursor; gc != NULL; gc = gc->next)
1669 fprintf (e, "// width: %d; height %d; planes %d; bits %d\n",
1670 gc->width, gc->height, gc->planes, gc->bits);
1671 fprintf (e, "// data bytes: %lu; index: %d\n",
1672 gc->bytes, gc->index);
1676 /* Write dialog data. */
1679 write_rc_dialog (e, dialog)
1681 const struct dialog *dialog;
1683 const struct dialog_control *control;
1685 if (dialog->style != 0)
1686 fprintf (e, "STYLE 0x%lx\n", dialog->style);
1687 if (dialog->exstyle != 0)
1688 fprintf (e, "EXSTYLE 0x%lx\n", dialog->exstyle);
1689 if (dialog->class.named || dialog->class.u.id != 0)
1691 fprintf (e, "CLASS ");
1692 res_id_print (e, dialog->class, 0);
1695 if (dialog->caption != NULL)
1697 fprintf (e, "CAPTION \"");
1698 unicode_print (e, dialog->caption, -1);
1699 fprintf (e, "\"\n");
1701 if (dialog->menu.named || dialog->menu.u.id != 0)
1703 fprintf (e, "MENU ");
1704 res_id_print (e, dialog->menu, 0);
1707 if (dialog->font != NULL)
1709 fprintf (e, "FONT %d, \"", dialog->pointsize);
1710 unicode_print (e, dialog->font, -1);
1712 if (dialog->ex != NULL
1713 && (dialog->ex->weight != 0 || dialog->ex->italic != 0))
1714 fprintf (e, ", %d, %d", dialog->ex->weight, dialog->ex->italic);
1718 fprintf (e, "BEGIN\n");
1720 for (control = dialog->controls; control != NULL; control = control->next)
1721 write_rc_dialog_control (e, control);
1723 fprintf (e, "END\n");
1726 /* For each predefined control keyword, this table provides the class
1732 unsigned short class;
1733 unsigned long style;
1736 static const struct control_info control_info[] =
1738 { "AUTO3STATE", CTL_BUTTON, BS_AUTO3STATE },
1739 { "AUTOCHECKBOX", CTL_BUTTON, BS_AUTOCHECKBOX },
1740 { "AUTORADIOBUTTON", CTL_BUTTON, BS_AUTORADIOBUTTON },
1741 { "CHECKBOX", CTL_BUTTON, BS_CHECKBOX },
1742 { "COMBOBOX", CTL_COMBOBOX, (unsigned long) -1 },
1743 { "CTEXT", CTL_STATIC, SS_CENTER },
1744 { "DEFPUSHBUTTON", CTL_BUTTON, BS_DEFPUSHBUTTON },
1745 { "EDITTEXT", CTL_EDIT, (unsigned long) -1 },
1746 { "GROUPBOX", CTL_BUTTON, BS_GROUPBOX },
1747 { "ICON", CTL_STATIC, SS_ICON },
1748 { "LISTBOX", CTL_LISTBOX, (unsigned long) -1 },
1749 { "LTEXT", CTL_STATIC, SS_LEFT },
1750 { "PUSHBOX", CTL_BUTTON, BS_PUSHBOX },
1751 { "PUSHBUTTON", CTL_BUTTON, BS_PUSHBUTTON },
1752 { "RADIOBUTTON", CTL_BUTTON, BS_RADIOBUTTON },
1753 { "RTEXT", CTL_STATIC, SS_RIGHT },
1754 { "SCROLLBAR", CTL_SCROLLBAR, (unsigned long) -1 },
1755 { "STATE3", CTL_BUTTON, BS_3STATE },
1756 /* It's important that USERBUTTON come after all the other button
1757 types, so that it won't be matched too early. */
1758 { "USERBUTTON", CTL_BUTTON, (unsigned long) -1 },
1762 /* Write a dialog control. */
1765 write_rc_dialog_control (e, control)
1767 const struct dialog_control *control;
1769 const struct control_info *ci;
1773 if (control->class.named)
1777 for (ci = control_info; ci->name != NULL; ++ci)
1778 if (ci->class == control->class.u.id
1779 && (ci->style == (unsigned long) -1
1780 || ci->style == (control->style & 0xff)))
1784 if (ci->name != NULL)
1785 fprintf (e, "%s", ci->name);
1787 fprintf (e, "CONTROL");
1789 if (control->text.named || control->text.u.id != 0)
1792 res_id_print (e, control->text, 1);
1796 fprintf (e, " %d, ", control->id);
1798 if (ci->name == NULL)
1800 res_id_print (e, control->class, 0);
1801 fprintf (e, ", 0x%lx, ", control->style);
1804 fprintf (e, "%d, %d", control->x, control->y);
1806 if (control->style != SS_ICON
1807 || control->exstyle != 0
1808 || control->width != 0
1809 || control->height != 0
1810 || control->help != 0)
1812 fprintf (e, ", %d, %d", control->width, control->height);
1814 /* FIXME: We don't need to print the style if it is the default.
1815 More importantly, in certain cases we actually need to turn
1816 off parts of the forced style, by using NOT. */
1817 fprintf (e, ", 0x%lx", control->style);
1819 if (control->exstyle != 0 || control->help != 0)
1820 fprintf (e, ", 0x%lx, %lu", control->exstyle, control->help);
1825 if (control->data != NULL)
1826 write_rc_rcdata (e, control->data, 2);
1829 /* Write out font directory data. This would normally be built from
1833 write_rc_fontdir (e, fontdir)
1835 const struct fontdir *fontdir;
1837 const struct fontdir *fc;
1839 for (fc = fontdir; fc != NULL; fc = fc->next)
1841 fprintf (e, "// Font index: %d\n", fc->index);
1842 write_rc_filedata (e, fc->length, fc->data);
1846 /* Write out group icon data. This would normally be built from the
1850 write_rc_group_icon (e, group_icon)
1852 const struct group_icon *group_icon;
1854 const struct group_icon *gi;
1856 for (gi = group_icon; gi != NULL; gi = gi->next)
1858 fprintf (e, "// width: %d; height %d; colors: %d; planes %d; bits %d\n",
1859 gi->width, gi->height, gi->colors, gi->planes, gi->bits);
1860 fprintf (e, "// data bytes: %lu; index: %d\n",
1861 gi->bytes, gi->index);
1865 /* Write out a menu resource. */
1868 write_rc_menu (e, menu, menuex)
1870 const struct menu *menu;
1873 if (menu->help != 0)
1874 fprintf (e, "// Help ID: %lu\n", menu->help);
1875 write_rc_menuitems (e, menu->items, menuex, 0);
1878 /* Write out menuitems. */
1881 write_rc_menuitems (e, menuitems, menuex, ind)
1883 const struct menuitem *menuitems;
1887 const struct menuitem *mi;
1890 fprintf (e, "BEGIN\n");
1892 for (mi = menuitems; mi != NULL; mi = mi->next)
1894 indent (e, ind + 2);
1896 if (mi->popup == NULL)
1897 fprintf (e, "MENUITEM");
1899 fprintf (e, "POPUP");
1902 && mi->popup == NULL
1907 fprintf (e, " SEPARATOR\n");
1911 if (mi->text == NULL)
1912 fprintf (e, " \"\"");
1916 unicode_print (e, mi->text, -1);
1922 if (mi->popup == NULL)
1923 fprintf (e, ", %d", mi->id);
1925 if ((mi->type & MENUITEM_CHECKED) != 0)
1926 fprintf (e, ", CHECKED");
1927 if ((mi->type & MENUITEM_GRAYED) != 0)
1928 fprintf (e, ", GRAYED");
1929 if ((mi->type & MENUITEM_HELP) != 0)
1930 fprintf (e, ", HELP");
1931 if ((mi->type & MENUITEM_INACTIVE) != 0)
1932 fprintf (e, ", INACTIVE");
1933 if ((mi->type & MENUITEM_MENUBARBREAK) != 0)
1934 fprintf (e, ", MENUBARBREAK");
1935 if ((mi->type & MENUITEM_MENUBREAK) != 0)
1936 fprintf (e, ", MENUBREAK");
1940 if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0)
1942 fprintf (e, ", %d", mi->id);
1943 if (mi->type != 0 || mi->state != 0 || mi->help != 0)
1945 fprintf (e, ", %lu", mi->type);
1946 if (mi->state != 0 || mi->help != 0)
1948 fprintf (e, ", %lu", mi->state);
1950 fprintf (e, ", %lu", mi->help);
1958 if (mi->popup != NULL)
1959 write_rc_menuitems (e, mi->popup, menuex, ind + 2);
1963 fprintf (e, "END\n");
1966 /* Write out an rcdata resource. This is also used for other types of
1967 resources that need to print arbitrary data. */
1970 write_rc_rcdata (e, rcdata, ind)
1972 const struct rcdata_item *rcdata;
1975 const struct rcdata_item *ri;
1978 fprintf (e, "BEGIN\n");
1980 for (ri = rcdata; ri != NULL; ri = ri->next)
1982 if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0)
1985 indent (e, ind + 2);
1993 fprintf (e, "%d", ri->u.word);
1997 fprintf (e, "%luL", ri->u.dword);
2007 for (i = 0; i < ri->u.string.length; i++)
2012 fprintf (e, "\\%03o", *s);
2018 case RCDATA_WSTRING:
2020 unicode_print (e, ri->u.wstring.w, ri->u.wstring.length);
2029 /* Assume little endian data. */
2032 for (i = 0; i + 3 < ri->u.buffer.length; i += 4)
2036 l = ((((((ri->u.buffer.data[i + 3] << 8)
2037 | ri->u.buffer.data[i + 2]) << 8)
2038 | ri->u.buffer.data[i + 1]) << 8)
2039 | ri->u.buffer.data[i]);
2045 indent (e, ind + 2);
2047 fprintf (e, "%luL", l);
2050 if (i + 1 < ri->u.buffer.length)
2054 i = (ri->u.buffer.data[i + 1] << 8) | ri->u.buffer.data[i];
2060 indent (e, ind + 2);
2062 fprintf (e, "%d", i);
2066 if (i < ri->u.buffer.length)
2073 indent (e, ind + 2);
2075 if ((ri->u.buffer.data[i] & 0x7f) == ri->u.buffer.data[i]
2076 && isprint (ri->u.buffer.data[i]))
2077 fprintf (e, "\"%c\"", ri->u.buffer.data[i]);
2079 fprintf (e, "\"\%03o\"", ri->u.buffer.data[i]);
2086 if (ri->next != NULL)
2092 fprintf (e, "END\n");
2095 /* Write out a stringtable resource. */
2098 write_rc_stringtable (e, name, stringtable)
2100 const struct res_id *name;
2101 const struct stringtable *stringtable;
2103 unsigned long offset;
2106 if (name != NULL && ! name->named)
2107 offset = name->u.id << 4;
2110 fprintf (e, "// %s string table name\n",
2111 name == NULL ? "Missing" : "Invalid");
2115 fprintf (e, "BEGIN\n");
2117 for (i = 0; i < 16; i++)
2119 if (stringtable->strings[i].length != 0)
2121 fprintf (e, " %lu, \"", offset + i);
2122 unicode_print (e, stringtable->strings[i].string,
2123 stringtable->strings[i].length);
2124 fprintf (e, "\"\n");
2128 fprintf (e, "END\n");
2131 /* Write out a versioninfo resource. */
2134 write_rc_versioninfo (e, versioninfo)
2136 const struct versioninfo *versioninfo;
2138 const struct fixed_versioninfo *f;
2139 const struct ver_info *vi;
2141 f = versioninfo->fixed;
2142 if (f->file_version_ms != 0 || f->file_version_ls != 0)
2143 fprintf (e, " FILEVERSION %lu, %lu, %lu, %lu\n",
2144 (f->file_version_ms >> 16) & 0xffff,
2145 f->file_version_ms & 0xffff,
2146 (f->file_version_ls >> 16) & 0xffff,
2147 f->file_version_ls & 0xffff);
2148 if (f->product_version_ms != 0 || f->product_version_ls != 0)
2149 fprintf (e, " PRODUCTVERSION %lu, %lu, %lu, %lu\n",
2150 (f->product_version_ms >> 16) & 0xffff,
2151 f->product_version_ms & 0xffff,
2152 (f->product_version_ls >> 16) & 0xffff,
2153 f->product_version_ls & 0xffff);
2154 if (f->file_flags_mask != 0)
2155 fprintf (e, " FILEFLAGSMASK 0x%lx\n", f->file_flags_mask);
2156 if (f->file_flags != 0)
2157 fprintf (e, " FILEFLAGS 0x%lx\n", f->file_flags);
2158 if (f->file_os != 0)
2159 fprintf (e, " FILEOS 0x%lx\n", f->file_os);
2160 if (f->file_type != 0)
2161 fprintf (e, " FILETYPE 0x%lx\n", f->file_type);
2162 if (f->file_subtype != 0)
2163 fprintf (e, " FILESUBTYPE 0x%lx\n", f->file_subtype);
2164 if (f->file_date_ms != 0 || f->file_date_ls != 0)
2165 fprintf (e, "// Date: %lu, %lu\n", f->file_date_ms, f->file_date_ls);
2167 fprintf (e, "BEGIN\n");
2169 for (vi = versioninfo->var; vi != NULL; vi = vi->next)
2173 case VERINFO_STRING:
2175 const struct ver_stringinfo *vs;
2177 fprintf (e, " BLOCK \"StringFileInfo\"\n");
2178 fprintf (e, " BEGIN\n");
2179 fprintf (e, " BLOCK \"");
2180 unicode_print (e, vi->u.string.language, -1);
2181 fprintf (e, "\"\n");
2182 fprintf (e, " BEGIN\n");
2184 for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
2186 fprintf (e, " VALUE \"");
2187 unicode_print (e, vs->key, -1);
2188 fprintf (e, "\", \"");
2189 unicode_print (e, vs->value, -1);
2190 fprintf (e, "\"\n");
2193 fprintf (e, " END\n");
2194 fprintf (e, " END\n");
2200 const struct ver_varinfo *vv;
2202 fprintf (e, " BLOCK \"VarFileInfo\"\n");
2203 fprintf (e, " BEGIN\n");
2204 fprintf (e, " VALUE \"");
2205 unicode_print (e, vi->u.var.key, -1);
2208 for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
2209 fprintf (e, ", 0x%x, %d", (unsigned int) vv->language,
2212 fprintf (e, "\n END\n");
2219 fprintf (e, "END\n");
2222 /* Write out data which would normally be read from a file. */
2225 write_rc_filedata (e, length, data)
2227 unsigned long length;
2228 const unsigned char *data;
2232 for (i = 0; i + 15 < length; i += 16)
2234 fprintf (e, "// %4lx: ", i);
2235 fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x ",
2236 data[i + 0], data[i + 1], data[i + 2], data[i + 3],
2237 data[i + 4], data[i + 5], data[i + 6], data[i + 7]);
2238 fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
2239 data[i + 8], data[i + 9], data[i + 10], data[i + 11],
2240 data[i + 12], data[i + 13], data[i + 14], data[i + 15]);
2245 fprintf (e, "// %4lx:", i);
2248 fprintf (e, " %02x", data[i]);