document behaviour of dot inside sections.
[binutils.git] / binutils / resrc.c
blob41c9ccacfbe101e7ed331766d3fb536357108f13
1 /* resrc.c -- read and write Windows rc files.
2 Copyright 1997, 1998 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 <sys/stat.h>
34 #if defined (_WIN32) && ! defined (__CYGWIN32__)
35 #define popen _popen
36 #define pclose _pclose
37 #endif
39 /* The default preprocessor. */
41 #define DEFAULT_PREPROCESSOR "gcc -E -xc-header -DRC_INVOKED"
43 /* We read the directory entries in a cursor or icon file into
44 instances of this structure. */
46 struct icondir
48 /* Width of image. */
49 unsigned char width;
50 /* Height of image. */
51 unsigned char height;
52 /* Number of colors in image. */
53 unsigned char colorcount;
54 union
56 struct
58 /* Color planes. */
59 unsigned short planes;
60 /* Bits per pixel. */
61 unsigned short bits;
62 } icon;
63 struct
65 /* X coordinate of hotspot. */
66 unsigned short xhotspot;
67 /* Y coordinate of hotspot. */
68 unsigned short yhotspot;
69 } cursor;
70 } u;
71 /* Bytes in image. */
72 unsigned long bytes;
73 /* File offset of image. */
74 unsigned long offset;
77 /* The name of the rc file we are reading. */
79 char *rc_filename;
81 /* The line number in the rc file. */
83 int rc_lineno;
85 /* The pipe we are reading from, so that we can close it if we exit. */
87 static FILE *cpp_pipe;
89 /* As we read the rc file, we attach information to this structure. */
91 static struct res_directory *resources;
93 /* The number of cursor resources we have written out. */
95 static int cursors;
97 /* The number of font resources we have written out. */
99 static int fonts;
101 /* Font directory information. */
103 struct fontdir *fontdirs;
105 /* Resource info to use for fontdirs. */
107 struct res_res_info fontdirs_resinfo;
109 /* The number of icon resources we have written out. */
111 static int icons;
113 /* Local functions. */
115 static void close_pipe PARAMS ((void));
116 static void unexpected_eof PARAMS ((const char *));
117 static int get_word PARAMS ((FILE *, const char *));
118 static unsigned long get_long PARAMS ((FILE *, const char *));
119 static void get_data
120 PARAMS ((FILE *, unsigned char *, unsigned long, const char *));
121 static void define_fontdirs PARAMS ((void));
123 /* look for the preprocessor program */
125 FILE *
126 look_for_default (cmd, prefix, end_prefix, preprocargs, filename)
127 char *cmd;
128 char *prefix;
129 int end_prefix;
130 char *preprocargs;
131 char *filename;
133 char *path = getenv ("PATH");
134 char *space;
135 int found;
136 struct stat s;
138 strcpy (cmd, prefix);
140 sprintf (cmd+end_prefix, "%s", DEFAULT_PREPROCESSOR);
141 space = strchr (cmd+end_prefix, ' ');
142 if (space)
143 *space = 0;
145 if (strchr (cmd, '/'))
147 found = stat (cmd, &s);
149 if (found < 0)
151 if (verbose)
152 fprintf (stderr, "Tried `%s'\n", cmd);
153 return 0;
157 strcpy (cmd, prefix);
159 sprintf (cmd+end_prefix, "%s %s %s",
160 DEFAULT_PREPROCESSOR, preprocargs, filename);
162 if (verbose)
163 fprintf (stderr, "Using `%s'\n", cmd);
165 cpp_pipe = popen (cmd, FOPEN_RT);
166 return cpp_pipe;
169 /* Read an rc file. */
171 struct res_directory *
172 read_rc_file (filename, preprocessor, preprocargs, language)
173 const char *filename;
174 const char *preprocessor;
175 const char *preprocargs;
176 int language;
178 char *cmd;
180 if (preprocargs == NULL)
181 preprocargs = "";
182 if (filename == NULL)
183 filename = "-";
185 if (preprocessor)
187 cmd = xmalloc (strlen (preprocessor)
188 + strlen (preprocargs)
189 + strlen (filename)
190 + 10);
191 sprintf (cmd, "%s %s %s", preprocessor, preprocargs, filename);
193 cpp_pipe = popen (cmd, FOPEN_RT);
195 else
197 char *dash, *slash, *cp;
199 preprocessor = DEFAULT_PREPROCESSOR;
201 cmd = xmalloc (strlen (program_name)
202 + strlen (preprocessor)
203 + strlen (preprocargs)
204 + strlen (filename)
205 + 10);
208 dash = slash = 0;
209 for (cp=program_name; *cp; cp++)
211 if (*cp == '-')
212 dash = cp;
213 if (
214 #if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__)
215 *cp == ':' || *cp == '\\' ||
216 #endif
217 *cp == '/')
219 slash = cp;
220 dash = 0;
224 cpp_pipe = 0;
226 if (dash)
228 /* First, try looking for a prefixed gcc in the windres
229 directory, with the same prefix as windres */
231 cpp_pipe = look_for_default (cmd, program_name, dash-program_name+1,
232 preprocargs, filename);
235 if (slash && !cpp_pipe)
237 /* Next, try looking for a gcc in the same directory as
238 that windres */
240 cpp_pipe = look_for_default (cmd, program_name, slash-program_name+1,
241 preprocargs, filename);
244 if (!cpp_pipe)
246 /* Sigh, try the default */
248 cpp_pipe = look_for_default (cmd, "", 0, preprocargs, filename);
252 if (cpp_pipe == NULL)
253 fatal (_("can't popen `%s': %s"), cmd, strerror (errno));
254 free (cmd);
256 xatexit (close_pipe);
258 rc_filename = xstrdup (filename);
259 rc_lineno = 1;
260 if (language != -1)
261 rcparse_set_language (language);
262 yyin = cpp_pipe;
263 yyparse ();
265 if (pclose (cpp_pipe) != 0)
266 fprintf (stderr, _("%s: warning: preprocessor failed\n"), program_name);
267 cpp_pipe = NULL;
269 if (fontdirs != NULL)
270 define_fontdirs ();
272 free (rc_filename);
273 rc_filename = NULL;
275 return resources;
278 /* Close the pipe if it is open. This is called via xatexit. */
280 void
281 close_pipe ()
283 if (cpp_pipe != NULL)
284 pclose (cpp_pipe);
287 /* Report an error while reading an rc file. */
289 void
290 yyerror (msg)
291 const char *msg;
293 fatal ("%s:%d: %s", rc_filename, rc_lineno, msg);
296 /* Issue a warning while reading an rc file. */
298 void
299 rcparse_warning (msg)
300 const char *msg;
302 fprintf (stderr, "%s:%d: %s\n", rc_filename, rc_lineno, msg);
305 /* Die if we get an unexpected end of file. */
307 static void
308 unexpected_eof (msg)
309 const char *msg;
311 fatal (_("%s: unexpected EOF"), msg);
314 /* Read a 16 bit word from a file. The data is assumed to be little
315 endian. */
317 static int
318 get_word (e, msg)
319 FILE *e;
320 const char *msg;
322 int b1, b2;
324 b1 = getc (e);
325 b2 = getc (e);
326 if (feof (e))
327 unexpected_eof (msg);
328 return ((b2 & 0xff) << 8) | (b1 & 0xff);
331 /* Read a 32 bit word from a file. The data is assumed to be little
332 endian. */
334 static unsigned long
335 get_long (e, msg)
336 FILE *e;
337 const char *msg;
339 int b1, b2, b3, b4;
341 b1 = getc (e);
342 b2 = getc (e);
343 b3 = getc (e);
344 b4 = getc (e);
345 if (feof (e))
346 unexpected_eof (msg);
347 return (((((((b4 & 0xff) << 8)
348 | (b3 & 0xff)) << 8)
349 | (b2 & 0xff)) << 8)
350 | (b1 & 0xff));
353 /* Read data from a file. This is a wrapper to do error checking. */
355 static void
356 get_data (e, p, c, msg)
357 FILE *e;
358 unsigned char *p;
359 unsigned long c;
360 const char *msg;
362 unsigned long got;
364 got = fread (p, 1, c, e);
365 if (got == c)
366 return;
368 fatal (_("%s: read of %lu returned %lu"), msg, c, got);
371 /* Define an accelerator resource. */
373 void
374 define_accelerator (id, resinfo, data)
375 struct res_id id;
376 const struct res_res_info *resinfo;
377 struct accelerator *data;
379 struct res_resource *r;
381 r = define_standard_resource (&resources, RT_ACCELERATOR, id,
382 resinfo->language, 0);
383 r->type = RES_TYPE_ACCELERATOR;
384 r->u.acc = data;
385 r->res_info = *resinfo;
388 /* Define a bitmap resource. Bitmap data is stored in a file. The
389 first 14 bytes of the file are a standard header, which is not
390 included in the resource data. */
392 #define BITMAP_SKIP (14)
394 void
395 define_bitmap (id, resinfo, filename)
396 struct res_id id;
397 const struct res_res_info *resinfo;
398 const char *filename;
400 FILE *e;
401 char *real_filename;
402 struct stat s;
403 unsigned char *data;
404 int i;
405 struct res_resource *r;
407 e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename);
409 if (stat (real_filename, &s) < 0)
410 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
411 strerror (errno));
413 data = (unsigned char *) res_alloc (s.st_size - BITMAP_SKIP);
415 for (i = 0; i < BITMAP_SKIP; i++)
416 getc (e);
418 get_data (e, data, s.st_size - BITMAP_SKIP, real_filename);
420 fclose (e);
421 free (real_filename);
423 r = define_standard_resource (&resources, RT_BITMAP, id,
424 resinfo->language, 0);
426 r->type = RES_TYPE_BITMAP;
427 r->u.data.length = s.st_size - BITMAP_SKIP;
428 r->u.data.data = data;
429 r->res_info = *resinfo;
432 /* Define a cursor resource. A cursor file may contain a set of
433 bitmaps, each representing the same cursor at various different
434 resolutions. They each get written out with a different ID. The
435 real cursor resource is then a group resource which can be used to
436 select one of the actual cursors. */
438 void
439 define_cursor (id, resinfo, filename)
440 struct res_id id;
441 const struct res_res_info *resinfo;
442 const char *filename;
444 FILE *e;
445 char *real_filename;
446 int type, count, i;
447 struct icondir *icondirs;
448 int first_cursor;
449 struct res_resource *r;
450 struct group_cursor *first, **pp;
452 e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename);
454 /* A cursor file is basically an icon file. The start of the file
455 is a three word structure. The first word is ignored. The
456 second word is the type of data. The third word is the number of
457 entries. */
459 get_word (e, real_filename);
460 type = get_word (e, real_filename);
461 count = get_word (e, real_filename);
462 if (type != 2)
463 fatal (_("cursor file `%s' does not contain cursor data"), real_filename);
465 /* Read in the icon directory entries. */
467 icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
469 for (i = 0; i < count; i++)
471 icondirs[i].width = getc (e);
472 icondirs[i].height = getc (e);
473 icondirs[i].colorcount = getc (e);
474 getc (e);
475 icondirs[i].u.cursor.xhotspot = get_word (e, real_filename);
476 icondirs[i].u.cursor.yhotspot = get_word (e, real_filename);
477 icondirs[i].bytes = get_long (e, real_filename);
478 icondirs[i].offset = get_long (e, real_filename);
480 if (feof (e))
481 unexpected_eof (real_filename);
484 /* Define each cursor as a unique resource. */
486 first_cursor = cursors;
488 for (i = 0; i < count; i++)
490 unsigned char *data;
491 struct res_id name;
492 struct cursor *c;
494 if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
495 fatal (_("%s: fseek to %lu failed: %s"), real_filename,
496 icondirs[i].offset, strerror (errno));
498 data = (unsigned char *) res_alloc (icondirs[i].bytes);
500 get_data (e, data, icondirs[i].bytes, real_filename);
502 c = (struct cursor *) res_alloc (sizeof *c);
503 c->xhotspot = icondirs[i].u.cursor.xhotspot;
504 c->yhotspot = icondirs[i].u.cursor.yhotspot;
505 c->length = icondirs[i].bytes;
506 c->data = data;
508 ++cursors;
510 name.named = 0;
511 name.u.id = cursors;
513 r = define_standard_resource (&resources, RT_CURSOR, name,
514 resinfo->language, 0);
515 r->type = RES_TYPE_CURSOR;
516 r->u.cursor = c;
517 r->res_info = *resinfo;
520 fclose (e);
521 free (real_filename);
523 /* Define a cursor group resource. */
525 first = NULL;
526 pp = &first;
527 for (i = 0; i < count; i++)
529 struct group_cursor *cg;
531 cg = (struct group_cursor *) res_alloc (sizeof *cg);
532 cg->next = NULL;
533 cg->width = icondirs[i].width;
534 cg->height = 2 * icondirs[i].height;
536 /* FIXME: What should these be set to? */
537 cg->planes = 1;
538 cg->bits = 1;
540 cg->bytes = icondirs[i].bytes + 4;
541 cg->index = first_cursor + i + 1;
543 *pp = cg;
544 pp = &(*pp)->next;
547 free (icondirs);
549 r = define_standard_resource (&resources, RT_GROUP_CURSOR, id,
550 resinfo->language, 0);
551 r->type = RES_TYPE_GROUP_CURSOR;
552 r->u.group_cursor = first;
553 r->res_info = *resinfo;
556 /* Define a dialog resource. */
558 void
559 define_dialog (id, resinfo, dialog)
560 struct res_id id;
561 const struct res_res_info *resinfo;
562 const struct dialog *dialog;
564 struct dialog *copy;
565 struct res_resource *r;
567 copy = (struct dialog *) res_alloc (sizeof *copy);
568 *copy = *dialog;
570 r = define_standard_resource (&resources, RT_DIALOG, id,
571 resinfo->language, 0);
572 r->type = RES_TYPE_DIALOG;
573 r->u.dialog = copy;
574 r->res_info = *resinfo;
577 /* Define a dialog control. This does not define a resource, but
578 merely allocates and fills in a structure. */
580 struct dialog_control *
581 define_control (text, id, x, y, width, height, class, style, exstyle)
582 const char *text;
583 unsigned long id;
584 unsigned long x;
585 unsigned long y;
586 unsigned long width;
587 unsigned long height;
588 unsigned long class;
589 unsigned long style;
590 unsigned long exstyle;
592 struct dialog_control *n;
594 n = (struct dialog_control *) res_alloc (sizeof *n);
595 n->next = NULL;
596 n->id = id;
597 n->style = style;
598 n->exstyle = exstyle;
599 n->x = x;
600 n->y = y;
601 n->width = width;
602 n->height = height;
603 n->class.named = 0;
604 n->class.u.id = class;
605 if (text != NULL)
606 res_string_to_id (&n->text, text);
607 else
609 n->text.named = 0;
610 n->text.u.id = 0;
612 n->data = NULL;
613 n->help = 0;
615 return n;
618 /* Define a font resource. */
620 void
621 define_font (id, resinfo, filename)
622 struct res_id id;
623 const struct res_res_info *resinfo;
624 const char *filename;
626 FILE *e;
627 char *real_filename;
628 struct stat s;
629 unsigned char *data;
630 struct res_resource *r;
631 long offset;
632 long fontdatalength;
633 unsigned char *fontdata;
634 struct fontdir *fd;
635 const char *device, *face;
636 struct fontdir **pp;
638 e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
640 if (stat (real_filename, &s) < 0)
641 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
642 strerror (errno));
644 data = (unsigned char *) res_alloc (s.st_size);
646 get_data (e, data, s.st_size, real_filename);
648 fclose (e);
649 free (real_filename);
651 r = define_standard_resource (&resources, RT_FONT, id,
652 resinfo->language, 0);
654 r->type = RES_TYPE_FONT;
655 r->u.data.length = s.st_size;
656 r->u.data.data = data;
657 r->res_info = *resinfo;
659 /* For each font resource, we must add an entry in the FONTDIR
660 resource. The FONTDIR resource includes some strings in the font
661 file. To find them, we have to do some magic on the data we have
662 read. */
664 offset = ((((((data[47] << 8)
665 | data[46]) << 8)
666 | data[45]) << 8)
667 | data[44]);
668 if (offset > 0 && offset < s.st_size)
669 device = (char *) data + offset;
670 else
671 device = "";
673 offset = ((((((data[51] << 8)
674 | data[50]) << 8)
675 | data[49]) << 8)
676 | data[48]);
677 if (offset > 0 && offset < s.st_size)
678 face = (char *) data + offset;
679 else
680 face = "";
682 ++fonts;
684 fontdatalength = 58 + strlen (device) + strlen (face);
685 fontdata = (unsigned char *) res_alloc (fontdatalength);
686 memcpy (fontdata, data, 56);
687 strcpy ((char *) fontdata + 56, device);
688 strcpy ((char *) fontdata + 57 + strlen (device), face);
690 fd = (struct fontdir *) res_alloc (sizeof *fd);
691 fd->next = NULL;
692 fd->index = fonts;
693 fd->length = fontdatalength;
694 fd->data = fontdata;
696 for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next)
698 *pp = fd;
700 /* For the single fontdirs resource, we always use the resource
701 information of the last font. I don't know what else to do. */
702 fontdirs_resinfo = *resinfo;
705 /* Define the fontdirs resource. This is called after the entire rc
706 file has been parsed, if any font resources were seen. */
708 static void
709 define_fontdirs ()
711 struct res_resource *r;
712 struct res_id id;
714 id.named = 0;
715 id.u.id = 1;
717 r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
719 r->type = RES_TYPE_FONTDIR;
720 r->u.fontdir = fontdirs;
721 r->res_info = fontdirs_resinfo;
724 /* Define an icon resource. An icon file may contain a set of
725 bitmaps, each representing the same icon at various different
726 resolutions. They each get written out with a different ID. The
727 real icon resource is then a group resource which can be used to
728 select one of the actual icon bitmaps. */
730 void
731 define_icon (id, resinfo, filename)
732 struct res_id id;
733 const struct res_res_info *resinfo;
734 const char *filename;
736 FILE *e;
737 char *real_filename;
738 int type, count, i;
739 struct icondir *icondirs;
740 int first_icon;
741 struct res_resource *r;
742 struct group_icon *first, **pp;
744 e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename);
746 /* The start of an icon file is a three word structure. The first
747 word is ignored. The second word is the type of data. The third
748 word is the number of entries. */
750 get_word (e, real_filename);
751 type = get_word (e, real_filename);
752 count = get_word (e, real_filename);
753 if (type != 1)
754 fatal (_("icon file `%s' does not contain icon data"), real_filename);
756 /* Read in the icon directory entries. */
758 icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
760 for (i = 0; i < count; i++)
762 icondirs[i].width = getc (e);
763 icondirs[i].height = getc (e);
764 icondirs[i].colorcount = getc (e);
765 getc (e);
766 icondirs[i].u.icon.planes = get_word (e, real_filename);
767 icondirs[i].u.icon.bits = get_word (e, real_filename);
768 icondirs[i].bytes = get_long (e, real_filename);
769 icondirs[i].offset = get_long (e, real_filename);
771 if (feof (e))
772 unexpected_eof (real_filename);
775 /* Define each icon as a unique resource. */
777 first_icon = icons;
779 for (i = 0; i < count; i++)
781 unsigned char *data;
782 struct res_id name;
784 if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
785 fatal (_("%s: fseek to %lu failed: %s"), real_filename,
786 icondirs[i].offset, strerror (errno));
788 data = (unsigned char *) res_alloc (icondirs[i].bytes);
790 get_data (e, data, icondirs[i].bytes, real_filename);
792 ++icons;
794 name.named = 0;
795 name.u.id = icons;
797 r = define_standard_resource (&resources, RT_ICON, name,
798 resinfo->language, 0);
799 r->type = RES_TYPE_ICON;
800 r->u.data.length = icondirs[i].bytes;
801 r->u.data.data = data;
802 r->res_info = *resinfo;
805 fclose (e);
806 free (real_filename);
808 /* Define an icon group resource. */
810 first = NULL;
811 pp = &first;
812 for (i = 0; i < count; i++)
814 struct group_icon *cg;
816 /* For some reason, at least in some files the planes and bits
817 are zero. We instead set them from the color. This is
818 copied from rcl. */
820 cg = (struct group_icon *) res_alloc (sizeof *cg);
821 cg->next = NULL;
822 cg->width = icondirs[i].width;
823 cg->height = icondirs[i].height;
824 cg->colors = icondirs[i].colorcount;
826 cg->planes = 1;
827 cg->bits = 0;
828 while ((1 << cg->bits) < cg->colors)
829 ++cg->bits;
831 cg->bytes = icondirs[i].bytes;
832 cg->index = first_icon + i + 1;
834 *pp = cg;
835 pp = &(*pp)->next;
838 free (icondirs);
840 r = define_standard_resource (&resources, RT_GROUP_ICON, id,
841 resinfo->language, 0);
842 r->type = RES_TYPE_GROUP_ICON;
843 r->u.group_icon = first;
844 r->res_info = *resinfo;
847 /* Define a menu resource. */
849 void
850 define_menu (id, resinfo, menuitems)
851 struct res_id id;
852 const struct res_res_info *resinfo;
853 struct menuitem *menuitems;
855 struct menu *m;
856 struct res_resource *r;
858 m = (struct menu *) res_alloc (sizeof *m);
859 m->items = menuitems;
860 m->help = 0;
862 r = define_standard_resource (&resources, RT_MENU, id, resinfo->language, 0);
863 r->type = RES_TYPE_MENU;
864 r->u.menu = m;
865 r->res_info = *resinfo;
868 /* Define a menu item. This does not define a resource, but merely
869 allocates and fills in a structure. */
871 struct menuitem *
872 define_menuitem (text, menuid, type, state, help, menuitems)
873 const char *text;
874 int menuid;
875 unsigned long type;
876 unsigned long state;
877 unsigned long help;
878 struct menuitem *menuitems;
880 struct menuitem *mi;
882 mi = (struct menuitem *) res_alloc (sizeof *mi);
883 mi->next = NULL;
884 mi->type = type;
885 mi->state = state;
886 mi->id = menuid;
887 if (text == NULL)
888 mi->text = NULL;
889 else
890 unicode_from_ascii ((int *) NULL, &mi->text, text);
891 mi->help = help;
892 mi->popup = menuitems;
893 return mi;
896 /* Define a messagetable resource. */
898 void
899 define_messagetable (id, resinfo, filename)
900 struct res_id id;
901 const struct res_res_info *resinfo;
902 const char *filename;
904 FILE *e;
905 char *real_filename;
906 struct stat s;
907 unsigned char *data;
908 struct res_resource *r;
910 e = open_file_search (filename, FOPEN_RB, "messagetable file",
911 &real_filename);
913 if (stat (real_filename, &s) < 0)
914 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
915 strerror (errno));
917 data = (unsigned char *) res_alloc (s.st_size);
919 get_data (e, data, s.st_size, real_filename);
921 fclose (e);
922 free (real_filename);
924 r = define_standard_resource (&resources, RT_MESSAGETABLE, id,
925 resinfo->language, 0);
927 r->type = RES_TYPE_MESSAGETABLE;
928 r->u.data.length = s.st_size;
929 r->u.data.data = data;
930 r->res_info = *resinfo;
933 /* Define an rcdata resource. */
935 void
936 define_rcdata (id, resinfo, data)
937 struct res_id id;
938 const struct res_res_info *resinfo;
939 struct rcdata_item *data;
941 struct res_resource *r;
943 r = define_standard_resource (&resources, RT_RCDATA, id,
944 resinfo->language, 0);
945 r->type = RES_TYPE_RCDATA;
946 r->u.rcdata = data;
947 r->res_info = *resinfo;
950 /* Create an rcdata item holding a string. */
952 struct rcdata_item *
953 define_rcdata_string (string, len)
954 const char *string;
955 unsigned long len;
957 struct rcdata_item *ri;
958 char *s;
960 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
961 ri->next = NULL;
962 ri->type = RCDATA_STRING;
963 ri->u.string.length = len;
964 s = (char *) res_alloc (len);
965 memcpy (s, string, len);
966 ri->u.string.s = s;
968 return ri;
971 /* Create an rcdata item holding a number. */
973 struct rcdata_item *
974 define_rcdata_number (val, dword)
975 unsigned long val;
976 int dword;
978 struct rcdata_item *ri;
980 ri = (struct rcdata_item *) res_alloc (sizeof *ri);
981 ri->next = NULL;
982 ri->type = dword ? RCDATA_DWORD : RCDATA_WORD;
983 ri->u.word = val;
985 return ri;
988 /* Define a stringtable resource. This is called for each string
989 which appears in a STRINGTABLE statement. */
991 void
992 define_stringtable (resinfo, stringid, string)
993 const struct res_res_info *resinfo;
994 unsigned long stringid;
995 const char *string;
997 struct res_id id;
998 struct res_resource *r;
1000 id.named = 0;
1001 id.u.id = (stringid >> 4) + 1;
1002 r = define_standard_resource (&resources, RT_STRING, id,
1003 resinfo->language, 1);
1005 if (r->type == RES_TYPE_UNINITIALIZED)
1007 int i;
1009 r->type = RES_TYPE_STRINGTABLE;
1010 r->u.stringtable = ((struct stringtable *)
1011 res_alloc (sizeof (struct stringtable)));
1012 for (i = 0; i < 16; i++)
1014 r->u.stringtable->strings[i].length = 0;
1015 r->u.stringtable->strings[i].string = NULL;
1018 r->res_info = *resinfo;
1021 unicode_from_ascii (&r->u.stringtable->strings[stringid & 0xf].length,
1022 &r->u.stringtable->strings[stringid & 0xf].string,
1023 string);
1026 /* Define a user data resource where the data is in the rc file. */
1028 void
1029 define_user_data (id, type, resinfo, data)
1030 struct res_id id;
1031 struct res_id type;
1032 const struct res_res_info *resinfo;
1033 struct rcdata_item *data;
1035 struct res_id ids[3];
1036 struct res_resource *r;
1038 ids[0] = type;
1039 ids[1] = id;
1040 ids[2].named = 0;
1041 ids[2].u.id = resinfo->language;
1043 r = define_resource (&resources, 3, ids, 0);
1044 r->type = RES_TYPE_USERDATA;
1045 r->u.userdata = data;
1046 r->res_info = *resinfo;
1049 /* Define a user data resource where the data is in a file. */
1051 void
1052 define_user_file (id, type, resinfo, filename)
1053 struct res_id id;
1054 struct res_id type;
1055 const struct res_res_info *resinfo;
1056 const char *filename;
1058 FILE *e;
1059 char *real_filename;
1060 struct stat s;
1061 unsigned char *data;
1062 struct res_id ids[3];
1063 struct res_resource *r;
1065 e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
1067 if (stat (real_filename, &s) < 0)
1068 fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
1069 strerror (errno));
1071 data = (unsigned char *) res_alloc (s.st_size);
1073 get_data (e, data, s.st_size, real_filename);
1075 fclose (e);
1076 free (real_filename);
1078 ids[0] = type;
1079 ids[1] = id;
1080 ids[2].named = 0;
1081 ids[2].u.id = resinfo->language;
1083 r = define_resource (&resources, 3, ids, 0);
1084 r->type = RES_TYPE_USERDATA;
1085 r->u.userdata = ((struct rcdata_item *)
1086 res_alloc (sizeof (struct rcdata_item)));
1087 r->u.userdata->next = NULL;
1088 r->u.userdata->type = RCDATA_BUFFER;
1089 r->u.userdata->u.buffer.length = s.st_size;
1090 r->u.userdata->u.buffer.data = data;
1091 r->res_info = *resinfo;
1094 /* Define a versioninfo resource. */
1096 void
1097 define_versioninfo (id, language, fixedverinfo, verinfo)
1098 struct res_id id;
1099 int language;
1100 struct fixed_versioninfo *fixedverinfo;
1101 struct ver_info *verinfo;
1103 struct res_resource *r;
1105 r = define_standard_resource (&resources, RT_VERSION, id, language, 0);
1106 r->type = RES_TYPE_VERSIONINFO;
1107 r->u.versioninfo = ((struct versioninfo *)
1108 res_alloc (sizeof (struct versioninfo)));
1109 r->u.versioninfo->fixed = fixedverinfo;
1110 r->u.versioninfo->var = verinfo;
1111 r->res_info.language = language;
1114 /* Add string version info to a list of version information. */
1116 struct ver_info *
1117 append_ver_stringfileinfo (verinfo, language, strings)
1118 struct ver_info *verinfo;
1119 const char *language;
1120 struct ver_stringinfo *strings;
1122 struct ver_info *vi, **pp;
1124 vi = (struct ver_info *) res_alloc (sizeof *vi);
1125 vi->next = NULL;
1126 vi->type = VERINFO_STRING;
1127 unicode_from_ascii ((int *) NULL, &vi->u.string.language, language);
1128 vi->u.string.strings = strings;
1130 for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1132 *pp = vi;
1134 return verinfo;
1137 /* Add variable version info to a list of version information. */
1139 struct ver_info *
1140 append_ver_varfileinfo (verinfo, key, var)
1141 struct ver_info *verinfo;
1142 const char *key;
1143 struct ver_varinfo *var;
1145 struct ver_info *vi, **pp;
1147 vi = (struct ver_info *) res_alloc (sizeof *vi);
1148 vi->next = NULL;
1149 vi->type = VERINFO_VAR;
1150 unicode_from_ascii ((int *) NULL, &vi->u.var.key, key);
1151 vi->u.var.var = var;
1153 for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1155 *pp = vi;
1157 return verinfo;
1160 /* Append version string information to a list. */
1162 struct ver_stringinfo *
1163 append_verval (strings, key, value)
1164 struct ver_stringinfo *strings;
1165 const char *key;
1166 const char *value;
1168 struct ver_stringinfo *vs, **pp;
1170 vs = (struct ver_stringinfo *) res_alloc (sizeof *vs);
1171 vs->next = NULL;
1172 unicode_from_ascii ((int *) NULL, &vs->key, key);
1173 unicode_from_ascii ((int *) NULL, &vs->value, value);
1175 for (pp = &strings; *pp != NULL; pp = &(*pp)->next)
1177 *pp = vs;
1179 return strings;
1182 /* Append version variable information to a list. */
1184 struct ver_varinfo *
1185 append_vertrans (var, language, charset)
1186 struct ver_varinfo *var;
1187 unsigned long language;
1188 unsigned long charset;
1190 struct ver_varinfo *vv, **pp;
1192 vv = (struct ver_varinfo *) res_alloc (sizeof *vv);
1193 vv->next = NULL;
1194 vv->language = language;
1195 vv->charset = charset;
1197 for (pp = &var; *pp != NULL; pp = &(*pp)->next)
1199 *pp = vv;
1201 return var;
1204 /* Local functions used to write out an rc file. */
1206 static void indent PARAMS ((FILE *, int));
1207 static void write_rc_directory
1208 PARAMS ((FILE *, const struct res_directory *, const struct res_id *,
1209 const struct res_id *, int *, int));
1210 static void write_rc_subdir
1211 PARAMS ((FILE *, const struct res_entry *, const struct res_id *,
1212 const struct res_id *, int *, int));
1213 static void write_rc_resource
1214 PARAMS ((FILE *, const struct res_id *, const struct res_id *,
1215 const struct res_resource *, int *));
1216 static void write_rc_accelerators
1217 PARAMS ((FILE *, const struct accelerator *));
1218 static void write_rc_cursor PARAMS ((FILE *, const struct cursor *));
1219 static void write_rc_group_cursor
1220 PARAMS ((FILE *, const struct group_cursor *));
1221 static void write_rc_dialog PARAMS ((FILE *, const struct dialog *));
1222 static void write_rc_dialog_control
1223 PARAMS ((FILE *, const struct dialog_control *));
1224 static void write_rc_fontdir PARAMS ((FILE *, const struct fontdir *));
1225 static void write_rc_group_icon PARAMS ((FILE *, const struct group_icon *));
1226 static void write_rc_menu PARAMS ((FILE *, const struct menu *, int));
1227 static void write_rc_menuitems
1228 PARAMS ((FILE *, const struct menuitem *, int, int));
1229 static void write_rc_rcdata PARAMS ((FILE *, const struct rcdata_item *, int));
1230 static void write_rc_stringtable
1231 PARAMS ((FILE *, const struct res_id *, const struct stringtable *));
1232 static void write_rc_versioninfo PARAMS ((FILE *, const struct versioninfo *));
1233 static void write_rc_filedata
1234 PARAMS ((FILE *, unsigned long, const unsigned char *));
1236 /* Indent a given number of spaces. */
1238 static void
1239 indent (e, c)
1240 FILE *e;
1241 int c;
1243 int i;
1245 for (i = 0; i < c; i++)
1246 putc (' ', e);
1249 /* Dump the resources we have read in the format of an rc file.
1251 Actually, we don't use the format of an rc file, because it's way
1252 too much of a pain--for example, we'd have to write icon resources
1253 into a file and refer to that file. We just generate a readable
1254 format that kind of looks like an rc file, and is useful for
1255 understanding the contents of a resource file. Someday we may want
1256 to generate an rc file which the rc compiler can read; if that day
1257 comes, this code will have to be fixed up. */
1259 void
1260 write_rc_file (filename, resources)
1261 const char *filename;
1262 const struct res_directory *resources;
1264 FILE *e;
1265 int language;
1267 if (filename == NULL)
1268 e = stdout;
1269 else
1271 e = fopen (filename, FOPEN_WT);
1272 if (e == NULL)
1273 fatal (_("can't open `%s' for output: %s"), filename, strerror (errno));
1276 language = -1;
1277 write_rc_directory (e, resources, (const struct res_id *) NULL,
1278 (const struct res_id *) NULL, &language, 1);
1281 /* Write out a directory. E is the file to write to. RD is the
1282 directory. TYPE is a pointer to the level 1 ID which serves as the
1283 resource type. NAME is a pointer to the level 2 ID which serves as
1284 an individual resource name. LANGUAGE is a pointer to the current
1285 language. LEVEL is the level in the tree. */
1287 static void
1288 write_rc_directory (e, rd, type, name, language, level)
1289 FILE *e;
1290 const struct res_directory *rd;
1291 const struct res_id *type;
1292 const struct res_id *name;
1293 int *language;
1294 int level;
1296 const struct res_entry *re;
1298 /* Print out some COFF information that rc files can't represent. */
1300 if (rd->time != 0)
1301 fprintf (e, "// Time stamp: %lu\n", rd->time);
1302 if (rd->characteristics != 0)
1303 fprintf (e, "// Characteristics: %lu\n", rd->characteristics);
1304 if (rd->major != 0 || rd->minor != 0)
1305 fprintf (e, "// Version: %d %d\n", rd->major, rd->minor);
1307 for (re = rd->entries; re != NULL; re = re->next)
1309 switch (level)
1311 case 1:
1312 /* If we're at level 1, the key of this resource is the
1313 type. This normally duplicates the information we have
1314 stored with the resource itself, but we need to remember
1315 the type if this is a user define resource type. */
1316 type = &re->id;
1317 break;
1319 case 2:
1320 /* If we're at level 2, the key of this resource is the name
1321 we are going to use in the rc printout. */
1322 name = &re->id;
1323 break;
1325 case 3:
1326 /* If we're at level 3, then this key represents a language.
1327 Use it to update the current language. */
1328 if (! re->id.named
1329 && re->id.u.id != (unsigned long) (unsigned int) *language
1330 && (re->id.u.id & 0xffff) == re->id.u.id)
1332 fprintf (e, "LANGUAGE %lu, %lu\n",
1333 re->id.u.id & 0xff, (re->id.u.id >> 8) & 0xff);
1334 *language = re->id.u.id;
1336 break;
1338 default:
1339 break;
1342 if (re->subdir)
1343 write_rc_subdir (e, re, type, name, language, level);
1344 else
1346 if (level == 3)
1348 /* This is the normal case: the three levels are
1349 TYPE/NAME/LANGUAGE. NAME will have been set at level
1350 2, and represents the name to use. We probably just
1351 set LANGUAGE, and it will probably match what the
1352 resource itself records if anything. */
1353 write_rc_resource (e, type, name, re->u.res, language);
1355 else
1357 fprintf (e, "// Resource at unexpected level %d\n", level);
1358 write_rc_resource (e, type, (struct res_id *) NULL, re->u.res,
1359 language);
1365 /* Write out a subdirectory entry. E is the file to write to. RE is
1366 the subdirectory entry. TYPE and NAME are pointers to higher level
1367 IDs, or NULL. LANGUAGE is a pointer to the current language.
1368 LEVEL is the level in the tree. */
1370 static void
1371 write_rc_subdir (e, re, type, name, language, level)
1372 FILE *e;
1373 const struct res_entry *re;
1374 const struct res_id *type;
1375 const struct res_id *name;
1376 int *language;
1377 int level;
1379 fprintf (e, "\n");
1380 switch (level)
1382 case 1:
1383 fprintf (e, "// Type: ");
1384 if (re->id.named)
1385 res_id_print (e, re->id, 1);
1386 else
1388 const char *s;
1390 switch (re->id.u.id)
1392 case RT_CURSOR: s = "cursor"; break;
1393 case RT_BITMAP: s = "bitmap"; break;
1394 case RT_ICON: s = "icon"; break;
1395 case RT_MENU: s = "menu"; break;
1396 case RT_DIALOG: s = "dialog"; break;
1397 case RT_STRING: s = "stringtable"; break;
1398 case RT_FONTDIR: s = "fontdir"; break;
1399 case RT_FONT: s = "font"; break;
1400 case RT_ACCELERATOR: s = "accelerators"; break;
1401 case RT_RCDATA: s = "rcdata"; break;
1402 case RT_MESSAGETABLE: s = "messagetable"; break;
1403 case RT_GROUP_CURSOR: s = "group cursor"; break;
1404 case RT_GROUP_ICON: s = "group icon"; break;
1405 case RT_VERSION: s = "version"; break;
1406 case RT_DLGINCLUDE: s = "dlginclude"; break;
1407 case RT_PLUGPLAY: s = "plugplay"; break;
1408 case RT_VXD: s = "vxd"; break;
1409 case RT_ANICURSOR: s = "anicursor"; break;
1410 case RT_ANIICON: s = "aniicon"; break;
1411 default: s = NULL; break;
1414 if (s != NULL)
1415 fprintf (e, "%s", s);
1416 else
1417 res_id_print (e, re->id, 1);
1419 fprintf (e, "\n");
1420 break;
1422 case 2:
1423 fprintf (e, "// Name: ");
1424 res_id_print (e, re->id, 1);
1425 fprintf (e, "\n");
1426 break;
1428 case 3:
1429 fprintf (e, "// Language: ");
1430 res_id_print (e, re->id, 1);
1431 fprintf (e, "\n");
1432 break;
1434 default:
1435 fprintf (e, "// Level %d: ", level);
1436 res_id_print (e, re->id, 1);
1437 fprintf (e, "\n");
1440 write_rc_directory (e, re->u.dir, type, name, language, level + 1);
1443 /* Write out a single resource. E is the file to write to. TYPE is a
1444 pointer to the type of the resource. NAME is a pointer to the name
1445 of the resource; it will be NULL if there is a level mismatch. RES
1446 is the resource data. LANGUAGE is a pointer to the current
1447 language. */
1449 static void
1450 write_rc_resource (e, type, name, res, language)
1451 FILE *e;
1452 const struct res_id *type;
1453 const struct res_id *name;
1454 const struct res_resource *res;
1455 int *language;
1457 const char *s;
1458 int rt;
1459 int menuex = 0;
1461 fprintf (e, "\n");
1463 switch (res->type)
1465 default:
1466 abort ();
1468 case RES_TYPE_ACCELERATOR:
1469 s = "ACCELERATOR";
1470 rt = RT_ACCELERATOR;
1471 break;
1473 case RES_TYPE_BITMAP:
1474 s = "BITMAP";
1475 rt = RT_BITMAP;
1476 break;
1478 case RES_TYPE_CURSOR:
1479 s = "CURSOR";
1480 rt = RT_CURSOR;
1481 break;
1483 case RES_TYPE_GROUP_CURSOR:
1484 s = "GROUP_CURSOR";
1485 rt = RT_GROUP_CURSOR;
1486 break;
1488 case RES_TYPE_DIALOG:
1489 if (extended_dialog (res->u.dialog))
1490 s = "DIALOGEX";
1491 else
1492 s = "DIALOG";
1493 rt = RT_DIALOG;
1494 break;
1496 case RES_TYPE_FONT:
1497 s = "FONT";
1498 rt = RT_FONT;
1499 break;
1501 case RES_TYPE_FONTDIR:
1502 s = "FONTDIR";
1503 rt = RT_FONTDIR;
1504 break;
1506 case RES_TYPE_ICON:
1507 s = "ICON";
1508 rt = RT_ICON;
1509 break;
1511 case RES_TYPE_GROUP_ICON:
1512 s = "GROUP_ICON";
1513 rt = RT_GROUP_ICON;
1514 break;
1516 case RES_TYPE_MENU:
1517 if (extended_menu (res->u.menu))
1519 s = "MENUEX";
1520 menuex = 1;
1522 else
1524 s = "MENU";
1525 menuex = 0;
1527 rt = RT_MENU;
1528 break;
1530 case RES_TYPE_MESSAGETABLE:
1531 s = "MESSAGETABLE";
1532 rt = RT_MESSAGETABLE;
1533 break;
1535 case RES_TYPE_RCDATA:
1536 s = "RCDATA";
1537 rt = RT_RCDATA;
1538 break;
1540 case RES_TYPE_STRINGTABLE:
1541 s = "STRINGTABLE";
1542 rt = RT_STRING;
1543 break;
1545 case RES_TYPE_USERDATA:
1546 s = NULL;
1547 rt = 0;
1548 break;
1550 case RES_TYPE_VERSIONINFO:
1551 s = "VERSIONINFO";
1552 rt = RT_VERSION;
1553 break;
1556 if (rt != 0
1557 && type != NULL
1558 && (type->named || type->u.id != (unsigned long) rt))
1560 fprintf (e, "// Unexpected resource type mismatch: ");
1561 res_id_print (e, *type, 1);
1562 fprintf (e, " != %d", rt);
1565 if (res->coff_info.codepage != 0)
1566 fprintf (e, "// Code page: %lu\n", res->coff_info.codepage);
1567 if (res->coff_info.reserved != 0)
1568 fprintf (e, "// COFF reserved value: %lu\n", res->coff_info.reserved);
1570 if (name != NULL)
1571 res_id_print (e, *name, 0);
1572 else
1573 fprintf (e, "??Unknown-Name??");
1575 fprintf (e, " ");
1576 if (s != NULL)
1577 fprintf (e, "%s", s);
1578 else if (type != NULL)
1579 res_id_print (e, *type, 0);
1580 else
1581 fprintf (e, "??Unknown-Type??");
1583 if (res->res_info.memflags != 0)
1585 if ((res->res_info.memflags & MEMFLAG_MOVEABLE) != 0)
1586 fprintf (e, " MOVEABLE");
1587 if ((res->res_info.memflags & MEMFLAG_PURE) != 0)
1588 fprintf (e, " PURE");
1589 if ((res->res_info.memflags & MEMFLAG_PRELOAD) != 0)
1590 fprintf (e, " PRELOAD");
1591 if ((res->res_info.memflags & MEMFLAG_DISCARDABLE) != 0)
1592 fprintf (e, " DISCARDABLE");
1595 if (res->type == RES_TYPE_DIALOG)
1597 fprintf (e, " %d, %d, %d, %d", res->u.dialog->x, res->u.dialog->y,
1598 res->u.dialog->width, res->u.dialog->height);
1599 if (res->u.dialog->ex != NULL
1600 && res->u.dialog->ex->help != 0)
1601 fprintf (e, ", %lu", res->u.dialog->ex->help);
1604 fprintf (e, "\n");
1606 if ((res->res_info.language != 0 && res->res_info.language != *language)
1607 || res->res_info.characteristics != 0
1608 || res->res_info.version != 0)
1610 int modifiers;
1612 switch (res->type)
1614 case RES_TYPE_ACCELERATOR:
1615 case RES_TYPE_DIALOG:
1616 case RES_TYPE_MENU:
1617 case RES_TYPE_RCDATA:
1618 case RES_TYPE_STRINGTABLE:
1619 modifiers = 1;
1620 break;
1622 default:
1623 modifiers = 0;
1624 break;
1627 if (res->res_info.language != 0 && res->res_info.language != *language)
1628 fprintf (e, "%sLANGUAGE %d, %d\n",
1629 modifiers ? "// " : "",
1630 res->res_info.language & 0xff,
1631 (res->res_info.language >> 8) & 0xff);
1632 if (res->res_info.characteristics != 0)
1633 fprintf (e, "%sCHARACTERISTICS %lu\n",
1634 modifiers ? "// " : "",
1635 res->res_info.characteristics);
1636 if (res->res_info.version != 0)
1637 fprintf (e, "%sVERSION %lu\n",
1638 modifiers ? "// " : "",
1639 res->res_info.version);
1642 switch (res->type)
1644 default:
1645 abort ();
1647 case RES_TYPE_ACCELERATOR:
1648 write_rc_accelerators (e, res->u.acc);
1649 break;
1651 case RES_TYPE_CURSOR:
1652 write_rc_cursor (e, res->u.cursor);
1653 break;
1655 case RES_TYPE_GROUP_CURSOR:
1656 write_rc_group_cursor (e, res->u.group_cursor);
1657 break;
1659 case RES_TYPE_DIALOG:
1660 write_rc_dialog (e, res->u.dialog);
1661 break;
1663 case RES_TYPE_FONTDIR:
1664 write_rc_fontdir (e, res->u.fontdir);
1665 break;
1667 case RES_TYPE_GROUP_ICON:
1668 write_rc_group_icon (e, res->u.group_icon);
1669 break;
1671 case RES_TYPE_MENU:
1672 write_rc_menu (e, res->u.menu, menuex);
1673 break;
1675 case RES_TYPE_RCDATA:
1676 write_rc_rcdata (e, res->u.rcdata, 0);
1677 break;
1679 case RES_TYPE_STRINGTABLE:
1680 write_rc_stringtable (e, name, res->u.stringtable);
1681 break;
1683 case RES_TYPE_USERDATA:
1684 write_rc_rcdata (e, res->u.userdata, 0);
1685 break;
1687 case RES_TYPE_VERSIONINFO:
1688 write_rc_versioninfo (e, res->u.versioninfo);
1689 break;
1691 case RES_TYPE_BITMAP:
1692 case RES_TYPE_FONT:
1693 case RES_TYPE_ICON:
1694 case RES_TYPE_MESSAGETABLE:
1695 write_rc_filedata (e, res->u.data.length, res->u.data.data);
1696 break;
1700 /* Write out accelerator information. */
1702 static void
1703 write_rc_accelerators (e, accelerators)
1704 FILE *e;
1705 const struct accelerator *accelerators;
1707 const struct accelerator *acc;
1709 fprintf (e, "BEGIN\n");
1710 for (acc = accelerators; acc != NULL; acc = acc->next)
1712 int printable;
1714 fprintf (e, " ");
1716 if ((acc->key & 0x7f) == acc->key
1717 && isprint ((unsigned char) acc->key)
1718 && (acc->flags & ACC_VIRTKEY) == 0)
1720 fprintf (e, "\"%c\"", acc->key);
1721 printable = 1;
1723 else
1725 fprintf (e, "%d", acc->key);
1726 printable = 0;
1729 fprintf (e, ", %d", acc->id);
1731 if (! printable)
1733 if ((acc->flags & ACC_VIRTKEY) != 0)
1734 fprintf (e, ", VIRTKEY");
1735 else
1736 fprintf (e, ", ASCII");
1739 if ((acc->flags & ACC_SHIFT) != 0)
1740 fprintf (e, ", SHIFT");
1741 if ((acc->flags & ACC_CONTROL) != 0)
1742 fprintf (e, ", CONTROL");
1743 if ((acc->flags & ACC_ALT) != 0)
1744 fprintf (e, ", ALT");
1746 fprintf (e, "\n");
1749 fprintf (e, "END\n");
1752 /* Write out cursor information. This would normally be in a separate
1753 file, which the rc file would include. */
1755 static void
1756 write_rc_cursor (e, cursor)
1757 FILE *e;
1758 const struct cursor *cursor;
1760 fprintf (e, "// Hotspot: x: %d; y: %d\n", cursor->xhotspot,
1761 cursor->yhotspot);
1762 write_rc_filedata (e, cursor->length, cursor->data);
1765 /* Write out group cursor data. This would normally be built from the
1766 cursor data. */
1768 static void
1769 write_rc_group_cursor (e, group_cursor)
1770 FILE *e;
1771 const struct group_cursor *group_cursor;
1773 const struct group_cursor *gc;
1775 for (gc = group_cursor; gc != NULL; gc = gc->next)
1777 fprintf (e, "// width: %d; height %d; planes %d; bits %d\n",
1778 gc->width, gc->height, gc->planes, gc->bits);
1779 fprintf (e, "// data bytes: %lu; index: %d\n",
1780 gc->bytes, gc->index);
1784 /* Write dialog data. */
1786 static void
1787 write_rc_dialog (e, dialog)
1788 FILE *e;
1789 const struct dialog *dialog;
1791 const struct dialog_control *control;
1793 if (dialog->style != 0)
1794 fprintf (e, "STYLE 0x%lx\n", dialog->style);
1795 if (dialog->exstyle != 0)
1796 fprintf (e, "EXSTYLE 0x%lx\n", dialog->exstyle);
1797 if ((dialog->class.named && dialog->class.u.n.length > 0)
1798 || dialog->class.u.id != 0)
1800 fprintf (e, "CLASS ");
1801 res_id_print (e, dialog->class, 0);
1802 fprintf (e, "\n");
1804 if (dialog->caption != NULL)
1806 fprintf (e, "CAPTION \"");
1807 unicode_print (e, dialog->caption, -1);
1808 fprintf (e, "\"\n");
1810 if ((dialog->menu.named && dialog->menu.u.n.length > 0)
1811 || dialog->menu.u.id != 0)
1813 fprintf (e, "MENU ");
1814 res_id_print (e, dialog->menu, 0);
1815 fprintf (e, "\n");
1817 if (dialog->font != NULL)
1819 fprintf (e, "FONT %d, \"", dialog->pointsize);
1820 unicode_print (e, dialog->font, -1);
1821 fprintf (e, "\"");
1822 if (dialog->ex != NULL
1823 && (dialog->ex->weight != 0 || dialog->ex->italic != 0))
1824 fprintf (e, ", %d, %d", dialog->ex->weight, dialog->ex->italic);
1825 fprintf (e, "\n");
1828 fprintf (e, "BEGIN\n");
1830 for (control = dialog->controls; control != NULL; control = control->next)
1831 write_rc_dialog_control (e, control);
1833 fprintf (e, "END\n");
1836 /* For each predefined control keyword, this table provides the class
1837 and the style. */
1839 struct control_info
1841 const char *name;
1842 unsigned short class;
1843 unsigned long style;
1846 static const struct control_info control_info[] =
1848 { "AUTO3STATE", CTL_BUTTON, BS_AUTO3STATE },
1849 { "AUTOCHECKBOX", CTL_BUTTON, BS_AUTOCHECKBOX },
1850 { "AUTORADIOBUTTON", CTL_BUTTON, BS_AUTORADIOBUTTON },
1851 { "CHECKBOX", CTL_BUTTON, BS_CHECKBOX },
1852 { "COMBOBOX", CTL_COMBOBOX, (unsigned long) -1 },
1853 { "CTEXT", CTL_STATIC, SS_CENTER },
1854 { "DEFPUSHBUTTON", CTL_BUTTON, BS_DEFPUSHBUTTON },
1855 { "EDITTEXT", CTL_EDIT, (unsigned long) -1 },
1856 { "GROUPBOX", CTL_BUTTON, BS_GROUPBOX },
1857 { "ICON", CTL_STATIC, SS_ICON },
1858 { "LISTBOX", CTL_LISTBOX, (unsigned long) -1 },
1859 { "LTEXT", CTL_STATIC, SS_LEFT },
1860 { "PUSHBOX", CTL_BUTTON, BS_PUSHBOX },
1861 { "PUSHBUTTON", CTL_BUTTON, BS_PUSHBUTTON },
1862 { "RADIOBUTTON", CTL_BUTTON, BS_RADIOBUTTON },
1863 { "RTEXT", CTL_STATIC, SS_RIGHT },
1864 { "SCROLLBAR", CTL_SCROLLBAR, (unsigned long) -1 },
1865 { "STATE3", CTL_BUTTON, BS_3STATE },
1866 /* It's important that USERBUTTON come after all the other button
1867 types, so that it won't be matched too early. */
1868 { "USERBUTTON", CTL_BUTTON, (unsigned long) -1 },
1869 { NULL, 0, 0 }
1872 /* Write a dialog control. */
1874 static void
1875 write_rc_dialog_control (e, control)
1876 FILE *e;
1877 const struct dialog_control *control;
1879 const struct control_info *ci;
1881 fprintf (e, " ");
1883 if (control->class.named)
1884 ci = NULL;
1885 else
1887 for (ci = control_info; ci->name != NULL; ++ci)
1888 if (ci->class == control->class.u.id
1889 && (ci->style == (unsigned long) -1
1890 || ci->style == (control->style & 0xff)))
1891 break;
1893 if (ci == NULL)
1894 fprintf (e, "CONTROL");
1895 else if (ci->name != NULL)
1896 fprintf (e, "%s", ci->name);
1897 else
1898 fprintf (e, "CONTROL");
1900 if (control->text.named || control->text.u.id != 0)
1902 fprintf (e, " ");
1903 res_id_print (e, control->text, 1);
1904 fprintf (e, ",");
1907 fprintf (e, " %d, ", control->id);
1909 if (ci == NULL)
1911 if (control->class.named)
1912 fprintf (e, "\"");
1913 res_id_print (e, control->class, 0);
1914 if (control->class.named)
1915 fprintf (e, "\"");
1916 fprintf (e, ", 0x%lx, ", control->style);
1919 fprintf (e, "%d, %d", control->x, control->y);
1921 if (control->style != SS_ICON
1922 || control->exstyle != 0
1923 || control->width != 0
1924 || control->height != 0
1925 || control->help != 0)
1927 fprintf (e, ", %d, %d", control->width, control->height);
1929 /* FIXME: We don't need to print the style if it is the default.
1930 More importantly, in certain cases we actually need to turn
1931 off parts of the forced style, by using NOT. */
1932 fprintf (e, ", 0x%lx", control->style);
1934 if (control->exstyle != 0 || control->help != 0)
1935 fprintf (e, ", 0x%lx, %lu", control->exstyle, control->help);
1938 fprintf (e, "\n");
1940 if (control->data != NULL)
1941 write_rc_rcdata (e, control->data, 2);
1944 /* Write out font directory data. This would normally be built from
1945 the font data. */
1947 static void
1948 write_rc_fontdir (e, fontdir)
1949 FILE *e;
1950 const struct fontdir *fontdir;
1952 const struct fontdir *fc;
1954 for (fc = fontdir; fc != NULL; fc = fc->next)
1956 fprintf (e, "// Font index: %d\n", fc->index);
1957 write_rc_filedata (e, fc->length, fc->data);
1961 /* Write out group icon data. This would normally be built from the
1962 icon data. */
1964 static void
1965 write_rc_group_icon (e, group_icon)
1966 FILE *e;
1967 const struct group_icon *group_icon;
1969 const struct group_icon *gi;
1971 for (gi = group_icon; gi != NULL; gi = gi->next)
1973 fprintf (e, "// width: %d; height %d; colors: %d; planes %d; bits %d\n",
1974 gi->width, gi->height, gi->colors, gi->planes, gi->bits);
1975 fprintf (e, "// data bytes: %lu; index: %d\n",
1976 gi->bytes, gi->index);
1980 /* Write out a menu resource. */
1982 static void
1983 write_rc_menu (e, menu, menuex)
1984 FILE *e;
1985 const struct menu *menu;
1986 int menuex;
1988 if (menu->help != 0)
1989 fprintf (e, "// Help ID: %lu\n", menu->help);
1990 write_rc_menuitems (e, menu->items, menuex, 0);
1993 /* Write out menuitems. */
1995 static void
1996 write_rc_menuitems (e, menuitems, menuex, ind)
1997 FILE *e;
1998 const struct menuitem *menuitems;
1999 int menuex;
2000 int ind;
2002 const struct menuitem *mi;
2004 indent (e, ind);
2005 fprintf (e, "BEGIN\n");
2007 for (mi = menuitems; mi != NULL; mi = mi->next)
2009 indent (e, ind + 2);
2011 if (mi->popup == NULL)
2012 fprintf (e, "MENUITEM");
2013 else
2014 fprintf (e, "POPUP");
2016 if (! menuex
2017 && mi->popup == NULL
2018 && mi->text == NULL
2019 && mi->type == 0
2020 && mi->id == 0)
2022 fprintf (e, " SEPARATOR\n");
2023 continue;
2026 if (mi->text == NULL)
2027 fprintf (e, " \"\"");
2028 else
2030 fprintf (e, " \"");
2031 unicode_print (e, mi->text, -1);
2032 fprintf (e, "\"");
2035 if (! menuex)
2037 if (mi->popup == NULL)
2038 fprintf (e, ", %d", mi->id);
2040 if ((mi->type & MENUITEM_CHECKED) != 0)
2041 fprintf (e, ", CHECKED");
2042 if ((mi->type & MENUITEM_GRAYED) != 0)
2043 fprintf (e, ", GRAYED");
2044 if ((mi->type & MENUITEM_HELP) != 0)
2045 fprintf (e, ", HELP");
2046 if ((mi->type & MENUITEM_INACTIVE) != 0)
2047 fprintf (e, ", INACTIVE");
2048 if ((mi->type & MENUITEM_MENUBARBREAK) != 0)
2049 fprintf (e, ", MENUBARBREAK");
2050 if ((mi->type & MENUITEM_MENUBREAK) != 0)
2051 fprintf (e, ", MENUBREAK");
2053 else
2055 if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0)
2057 fprintf (e, ", %d", mi->id);
2058 if (mi->type != 0 || mi->state != 0 || mi->help != 0)
2060 fprintf (e, ", %lu", mi->type);
2061 if (mi->state != 0 || mi->help != 0)
2063 fprintf (e, ", %lu", mi->state);
2064 if (mi->help != 0)
2065 fprintf (e, ", %lu", mi->help);
2071 fprintf (e, "\n");
2073 if (mi->popup != NULL)
2074 write_rc_menuitems (e, mi->popup, menuex, ind + 2);
2077 indent (e, ind);
2078 fprintf (e, "END\n");
2081 /* Write out an rcdata resource. This is also used for other types of
2082 resources that need to print arbitrary data. */
2084 static void
2085 write_rc_rcdata (e, rcdata, ind)
2086 FILE *e;
2087 const struct rcdata_item *rcdata;
2088 int ind;
2090 const struct rcdata_item *ri;
2092 indent (e, ind);
2093 fprintf (e, "BEGIN\n");
2095 for (ri = rcdata; ri != NULL; ri = ri->next)
2097 if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0)
2098 continue;
2100 indent (e, ind + 2);
2102 switch (ri->type)
2104 default:
2105 abort ();
2107 case RCDATA_WORD:
2108 fprintf (e, "%d", ri->u.word);
2109 break;
2111 case RCDATA_DWORD:
2112 fprintf (e, "%luL", ri->u.dword);
2113 break;
2115 case RCDATA_STRING:
2117 const char *s;
2118 unsigned long i;
2120 fprintf (e, "\"");
2121 s = ri->u.string.s;
2122 for (i = 0; i < ri->u.string.length; i++)
2124 if (isprint ((unsigned char) *s))
2125 putc (*s, e);
2126 else
2127 fprintf (e, "\\%03o", *s);
2129 fprintf (e, "\"");
2130 break;
2133 case RCDATA_WSTRING:
2134 fprintf (e, "L\"");
2135 unicode_print (e, ri->u.wstring.w, ri->u.wstring.length);
2136 fprintf (e, "\"");
2137 break;
2139 case RCDATA_BUFFER:
2141 unsigned long i;
2142 int first;
2144 /* Assume little endian data. */
2146 first = 1;
2147 for (i = 0; i + 3 < ri->u.buffer.length; i += 4)
2149 unsigned long l;
2151 l = ((((((ri->u.buffer.data[i + 3] << 8)
2152 | ri->u.buffer.data[i + 2]) << 8)
2153 | ri->u.buffer.data[i + 1]) << 8)
2154 | ri->u.buffer.data[i]);
2155 if (first)
2156 first = 0;
2157 else
2159 fprintf (e, ",\n");
2160 indent (e, ind + 2);
2162 fprintf (e, "%luL", l);
2165 if (i + 1 < ri->u.buffer.length)
2167 int i;
2169 i = (ri->u.buffer.data[i + 1] << 8) | ri->u.buffer.data[i];
2170 if (first)
2171 first = 0;
2172 else
2174 fprintf (e, ",\n");
2175 indent (e, ind + 2);
2177 fprintf (e, "%d", i);
2178 i += 2;
2181 if (i < ri->u.buffer.length)
2183 if (first)
2184 first = 0;
2185 else
2187 fprintf (e, ",\n");
2188 indent (e, ind + 2);
2190 if ((ri->u.buffer.data[i] & 0x7f) == ri->u.buffer.data[i]
2191 && isprint (ri->u.buffer.data[i]))
2192 fprintf (e, "\"%c\"", ri->u.buffer.data[i]);
2193 else
2194 fprintf (e, "\"\%03o\"", ri->u.buffer.data[i]);
2197 break;
2201 if (ri->next != NULL)
2202 fprintf (e, ",");
2203 fprintf (e, "\n");
2206 indent (e, ind);
2207 fprintf (e, "END\n");
2210 /* Write out a stringtable resource. */
2212 static void
2213 write_rc_stringtable (e, name, stringtable)
2214 FILE *e;
2215 const struct res_id *name;
2216 const struct stringtable *stringtable;
2218 unsigned long offset;
2219 int i;
2221 if (name != NULL && ! name->named)
2222 offset = (name->u.id - 1) << 4;
2223 else
2225 fprintf (e, "// %s string table name\n",
2226 name == NULL ? "Missing" : "Invalid");
2227 offset = 0;
2230 fprintf (e, "BEGIN\n");
2232 for (i = 0; i < 16; i++)
2234 if (stringtable->strings[i].length != 0)
2236 fprintf (e, " %lu, \"", offset + i);
2237 unicode_print (e, stringtable->strings[i].string,
2238 stringtable->strings[i].length);
2239 fprintf (e, "\"\n");
2243 fprintf (e, "END\n");
2246 /* Write out a versioninfo resource. */
2248 static void
2249 write_rc_versioninfo (e, versioninfo)
2250 FILE *e;
2251 const struct versioninfo *versioninfo;
2253 const struct fixed_versioninfo *f;
2254 const struct ver_info *vi;
2256 f = versioninfo->fixed;
2257 if (f->file_version_ms != 0 || f->file_version_ls != 0)
2258 fprintf (e, " FILEVERSION %lu, %lu, %lu, %lu\n",
2259 (f->file_version_ms >> 16) & 0xffff,
2260 f->file_version_ms & 0xffff,
2261 (f->file_version_ls >> 16) & 0xffff,
2262 f->file_version_ls & 0xffff);
2263 if (f->product_version_ms != 0 || f->product_version_ls != 0)
2264 fprintf (e, " PRODUCTVERSION %lu, %lu, %lu, %lu\n",
2265 (f->product_version_ms >> 16) & 0xffff,
2266 f->product_version_ms & 0xffff,
2267 (f->product_version_ls >> 16) & 0xffff,
2268 f->product_version_ls & 0xffff);
2269 if (f->file_flags_mask != 0)
2270 fprintf (e, " FILEFLAGSMASK 0x%lx\n", f->file_flags_mask);
2271 if (f->file_flags != 0)
2272 fprintf (e, " FILEFLAGS 0x%lx\n", f->file_flags);
2273 if (f->file_os != 0)
2274 fprintf (e, " FILEOS 0x%lx\n", f->file_os);
2275 if (f->file_type != 0)
2276 fprintf (e, " FILETYPE 0x%lx\n", f->file_type);
2277 if (f->file_subtype != 0)
2278 fprintf (e, " FILESUBTYPE 0x%lx\n", f->file_subtype);
2279 if (f->file_date_ms != 0 || f->file_date_ls != 0)
2280 fprintf (e, "// Date: %lu, %lu\n", f->file_date_ms, f->file_date_ls);
2282 fprintf (e, "BEGIN\n");
2284 for (vi = versioninfo->var; vi != NULL; vi = vi->next)
2286 switch (vi->type)
2288 case VERINFO_STRING:
2290 const struct ver_stringinfo *vs;
2292 fprintf (e, " BLOCK \"StringFileInfo\"\n");
2293 fprintf (e, " BEGIN\n");
2294 fprintf (e, " BLOCK \"");
2295 unicode_print (e, vi->u.string.language, -1);
2296 fprintf (e, "\"\n");
2297 fprintf (e, " BEGIN\n");
2299 for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
2301 fprintf (e, " VALUE \"");
2302 unicode_print (e, vs->key, -1);
2303 fprintf (e, "\", \"");
2304 unicode_print (e, vs->value, -1);
2305 fprintf (e, "\"\n");
2308 fprintf (e, " END\n");
2309 fprintf (e, " END\n");
2310 break;
2313 case VERINFO_VAR:
2315 const struct ver_varinfo *vv;
2317 fprintf (e, " BLOCK \"VarFileInfo\"\n");
2318 fprintf (e, " BEGIN\n");
2319 fprintf (e, " VALUE \"");
2320 unicode_print (e, vi->u.var.key, -1);
2321 fprintf (e, "\"");
2323 for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
2324 fprintf (e, ", 0x%x, %d", (unsigned int) vv->language,
2325 vv->charset);
2327 fprintf (e, "\n END\n");
2329 break;
2334 fprintf (e, "END\n");
2337 /* Write out data which would normally be read from a file. */
2339 static void
2340 write_rc_filedata (e, length, data)
2341 FILE *e;
2342 unsigned long length;
2343 const unsigned char *data;
2345 unsigned long i;
2347 for (i = 0; i + 15 < length; i += 16)
2349 fprintf (e, "// %4lx: ", i);
2350 fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x ",
2351 data[i + 0], data[i + 1], data[i + 2], data[i + 3],
2352 data[i + 4], data[i + 5], data[i + 6], data[i + 7]);
2353 fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
2354 data[i + 8], data[i + 9], data[i + 10], data[i + 11],
2355 data[i + 12], data[i + 13], data[i + 14], data[i + 15]);
2358 if (i < length)
2360 fprintf (e, "// %4lx:", i);
2361 while (i < length)
2363 fprintf (e, " %02x", data[i]);
2364 ++i;
2366 fprintf (e, "\n");