1*56bb7041Schristos /* resrc.c -- read and write Windows rc files.
2*56bb7041Schristos    Copyright (C) 1997-2020 Free Software Foundation, Inc.
3*56bb7041Schristos    Written by Ian Lance Taylor, Cygnus Support.
4*56bb7041Schristos    Rewritten by Kai Tietz, Onevision.
5*56bb7041Schristos 
6*56bb7041Schristos    This file is part of GNU Binutils.
7*56bb7041Schristos 
8*56bb7041Schristos    This program is free software; you can redistribute it and/or modify
9*56bb7041Schristos    it under the terms of the GNU General Public License as published by
10*56bb7041Schristos    the Free Software Foundation; either version 3 of the License, or
11*56bb7041Schristos    (at your option) any later version.
12*56bb7041Schristos 
13*56bb7041Schristos    This program is distributed in the hope that it will be useful,
14*56bb7041Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
15*56bb7041Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16*56bb7041Schristos    GNU General Public License for more details.
17*56bb7041Schristos 
18*56bb7041Schristos    You should have received a copy of the GNU General Public License
19*56bb7041Schristos    along with this program; if not, write to the Free Software
20*56bb7041Schristos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
21*56bb7041Schristos    02110-1301, USA.  */
22*56bb7041Schristos 
23*56bb7041Schristos /* This file contains functions that read and write Windows rc files.
24*56bb7041Schristos    These are text files that represent resources.  */
25*56bb7041Schristos 
26*56bb7041Schristos #include "sysdep.h"
27*56bb7041Schristos #include "bfd.h"
28*56bb7041Schristos #include "bucomm.h"
29*56bb7041Schristos #include "libiberty.h"
30*56bb7041Schristos #include "safe-ctype.h"
31*56bb7041Schristos #include "windres.h"
32*56bb7041Schristos 
33*56bb7041Schristos #include <assert.h>
34*56bb7041Schristos 
35*56bb7041Schristos #ifdef HAVE_SYS_WAIT_H
36*56bb7041Schristos #include <sys/wait.h>
37*56bb7041Schristos #else /* ! HAVE_SYS_WAIT_H */
38*56bb7041Schristos #if ! defined (_WIN32) || defined (__CYGWIN__)
39*56bb7041Schristos #ifndef WIFEXITED
40*56bb7041Schristos #define WIFEXITED(w)	(((w)&0377) == 0)
41*56bb7041Schristos #endif
42*56bb7041Schristos #ifndef WIFSIGNALED
43*56bb7041Schristos #define WIFSIGNALED(w)	(((w)&0377) != 0177 && ((w)&~0377) == 0)
44*56bb7041Schristos #endif
45*56bb7041Schristos #ifndef WTERMSIG
46*56bb7041Schristos #define WTERMSIG(w)	((w) & 0177)
47*56bb7041Schristos #endif
48*56bb7041Schristos #ifndef WEXITSTATUS
49*56bb7041Schristos #define WEXITSTATUS(w)	(((w) >> 8) & 0377)
50*56bb7041Schristos #endif
51*56bb7041Schristos #else /* defined (_WIN32) && ! defined (__CYGWIN__) */
52*56bb7041Schristos #ifndef WIFEXITED
53*56bb7041Schristos #define WIFEXITED(w)	(((w) & 0xff) == 0)
54*56bb7041Schristos #endif
55*56bb7041Schristos #ifndef WIFSIGNALED
56*56bb7041Schristos #define WIFSIGNALED(w)	(((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
57*56bb7041Schristos #endif
58*56bb7041Schristos #ifndef WTERMSIG
59*56bb7041Schristos #define WTERMSIG(w)	((w) & 0x7f)
60*56bb7041Schristos #endif
61*56bb7041Schristos #ifndef WEXITSTATUS
62*56bb7041Schristos #define WEXITSTATUS(w)	(((w) & 0xff00) >> 8)
63*56bb7041Schristos #endif
64*56bb7041Schristos #endif /* defined (_WIN32) && ! defined (__CYGWIN__) */
65*56bb7041Schristos #endif /* ! HAVE_SYS_WAIT_H */
66*56bb7041Schristos 
67*56bb7041Schristos #ifndef STDOUT_FILENO
68*56bb7041Schristos #define STDOUT_FILENO 1
69*56bb7041Schristos #endif
70*56bb7041Schristos 
71*56bb7041Schristos #if defined (_WIN32) && ! defined (__CYGWIN__)
72*56bb7041Schristos #define popen _popen
73*56bb7041Schristos #define pclose _pclose
74*56bb7041Schristos #endif
75*56bb7041Schristos 
76*56bb7041Schristos /* The default preprocessor.  */
77*56bb7041Schristos 
78*56bb7041Schristos #define DEFAULT_PREPROCESSOR "gcc -E -xc -DRC_INVOKED"
79*56bb7041Schristos 
80*56bb7041Schristos /* We read the directory entries in a cursor or icon file into
81*56bb7041Schristos    instances of this structure.  */
82*56bb7041Schristos 
83*56bb7041Schristos struct icondir
84*56bb7041Schristos {
85*56bb7041Schristos   /* Width of image.  */
86*56bb7041Schristos   bfd_byte width;
87*56bb7041Schristos   /* Height of image.  */
88*56bb7041Schristos   bfd_byte height;
89*56bb7041Schristos   /* Number of colors in image.  */
90*56bb7041Schristos   bfd_byte colorcount;
91*56bb7041Schristos   union
92*56bb7041Schristos   {
93*56bb7041Schristos     struct
94*56bb7041Schristos     {
95*56bb7041Schristos       /* Color planes.  */
96*56bb7041Schristos       unsigned short planes;
97*56bb7041Schristos       /* Bits per pixel.  */
98*56bb7041Schristos       unsigned short bits;
99*56bb7041Schristos     } icon;
100*56bb7041Schristos     struct
101*56bb7041Schristos     {
102*56bb7041Schristos       /* X coordinate of hotspot.  */
103*56bb7041Schristos       unsigned short xhotspot;
104*56bb7041Schristos       /* Y coordinate of hotspot.  */
105*56bb7041Schristos       unsigned short yhotspot;
106*56bb7041Schristos     } cursor;
107*56bb7041Schristos   } u;
108*56bb7041Schristos   /* Bytes in image.  */
109*56bb7041Schristos   unsigned long bytes;
110*56bb7041Schristos   /* File offset of image.  */
111*56bb7041Schristos   unsigned long offset;
112*56bb7041Schristos };
113*56bb7041Schristos 
114*56bb7041Schristos /* The name of the rc file we are reading.  */
115*56bb7041Schristos 
116*56bb7041Schristos char *rc_filename;
117*56bb7041Schristos 
118*56bb7041Schristos /* The line number in the rc file.  */
119*56bb7041Schristos 
120*56bb7041Schristos int rc_lineno;
121*56bb7041Schristos 
122*56bb7041Schristos /* The pipe we are reading from, so that we can close it if we exit.  */
123*56bb7041Schristos 
124*56bb7041Schristos FILE *cpp_pipe;
125*56bb7041Schristos 
126*56bb7041Schristos /* The temporary file used if we're not using popen, so we can delete it
127*56bb7041Schristos    if we exit.  */
128*56bb7041Schristos 
129*56bb7041Schristos static char *cpp_temp_file;
130*56bb7041Schristos 
131*56bb7041Schristos /* Input stream is either a file or a pipe.  */
132*56bb7041Schristos 
133*56bb7041Schristos static enum {ISTREAM_PIPE, ISTREAM_FILE} istream_type;
134*56bb7041Schristos 
135*56bb7041Schristos /* As we read the rc file, we attach information to this structure.  */
136*56bb7041Schristos 
137*56bb7041Schristos static rc_res_directory *resources;
138*56bb7041Schristos 
139*56bb7041Schristos /* The number of cursor resources we have written out.  */
140*56bb7041Schristos 
141*56bb7041Schristos static int cursors;
142*56bb7041Schristos 
143*56bb7041Schristos /* The number of font resources we have written out.  */
144*56bb7041Schristos 
145*56bb7041Schristos static int fonts;
146*56bb7041Schristos 
147*56bb7041Schristos /* Font directory information.  */
148*56bb7041Schristos 
149*56bb7041Schristos rc_fontdir *fontdirs;
150*56bb7041Schristos 
151*56bb7041Schristos /* Resource info to use for fontdirs.  */
152*56bb7041Schristos 
153*56bb7041Schristos rc_res_res_info fontdirs_resinfo;
154*56bb7041Schristos 
155*56bb7041Schristos /* The number of icon resources we have written out.  */
156*56bb7041Schristos 
157*56bb7041Schristos static int icons;
158*56bb7041Schristos 
159*56bb7041Schristos /* The windres target bfd .  */
160*56bb7041Schristos 
161*56bb7041Schristos static windres_bfd wrtarget =
162*56bb7041Schristos {
163*56bb7041Schristos   (bfd *) NULL, (asection *) NULL, WR_KIND_TARGET
164*56bb7041Schristos };
165*56bb7041Schristos 
166*56bb7041Schristos /* Local functions for rcdata based resource definitions.  */
167*56bb7041Schristos 
168*56bb7041Schristos static void define_font_rcdata (rc_res_id, const rc_res_res_info *,
169*56bb7041Schristos 				rc_rcdata_item *);
170*56bb7041Schristos static void define_icon_rcdata (rc_res_id, const rc_res_res_info *,
171*56bb7041Schristos 				rc_rcdata_item *);
172*56bb7041Schristos static void define_bitmap_rcdata (rc_res_id, const rc_res_res_info *,
173*56bb7041Schristos 				  rc_rcdata_item *);
174*56bb7041Schristos static void define_cursor_rcdata (rc_res_id, const rc_res_res_info *,
175*56bb7041Schristos 				  rc_rcdata_item *);
176*56bb7041Schristos static void define_fontdir_rcdata (rc_res_id, const rc_res_res_info *,
177*56bb7041Schristos 				   rc_rcdata_item *);
178*56bb7041Schristos static void define_messagetable_rcdata (rc_res_id, const rc_res_res_info *,
179*56bb7041Schristos 					rc_rcdata_item *);
180*56bb7041Schristos static rc_uint_type rcdata_copy (const rc_rcdata_item *, bfd_byte *);
181*56bb7041Schristos static bfd_byte *rcdata_render_as_buffer (const rc_rcdata_item *, rc_uint_type *);
182*56bb7041Schristos 
183*56bb7041Schristos static int run_cmd (char *, const char *);
184*56bb7041Schristos static FILE *open_input_stream (char *);
185*56bb7041Schristos static FILE *look_for_default
186*56bb7041Schristos   (char *, const char *, int, const char *, const char *);
187*56bb7041Schristos static void close_input_stream (void);
188*56bb7041Schristos static void unexpected_eof (const char *);
189*56bb7041Schristos static int get_word (FILE *, const char *);
190*56bb7041Schristos static unsigned long get_long (FILE *, const char *);
191*56bb7041Schristos static void get_data (FILE *, bfd_byte *, rc_uint_type, const char *);
192*56bb7041Schristos static void define_fontdirs (void);
193*56bb7041Schristos 
194*56bb7041Schristos /* Run `cmd' and redirect the output to `redir'.  */
195*56bb7041Schristos 
196*56bb7041Schristos static int
run_cmd(char * cmd,const char * redir)197*56bb7041Schristos run_cmd (char *cmd, const char *redir)
198*56bb7041Schristos {
199*56bb7041Schristos   char *s;
200*56bb7041Schristos   int pid, wait_status, retcode;
201*56bb7041Schristos   int i;
202*56bb7041Schristos   const char **argv;
203*56bb7041Schristos   char *errmsg_fmt, *errmsg_arg;
204*56bb7041Schristos   char *temp_base = choose_temp_base ();
205*56bb7041Schristos   int in_quote;
206*56bb7041Schristos   char sep;
207*56bb7041Schristos   int redir_handle = -1;
208*56bb7041Schristos   int stdout_save = -1;
209*56bb7041Schristos 
210*56bb7041Schristos   /* Count the args.  */
211*56bb7041Schristos   i = 0;
212*56bb7041Schristos 
213*56bb7041Schristos   for (s = cmd; *s; s++)
214*56bb7041Schristos     if (*s == ' ')
215*56bb7041Schristos       i++;
216*56bb7041Schristos 
217*56bb7041Schristos   i++;
218*56bb7041Schristos   argv = xmalloc (sizeof (char *) * (i + 3));
219*56bb7041Schristos   i = 0;
220*56bb7041Schristos   s = cmd;
221*56bb7041Schristos 
222*56bb7041Schristos   while (1)
223*56bb7041Schristos     {
224*56bb7041Schristos       while (*s == ' ' && *s != 0)
225*56bb7041Schristos 	s++;
226*56bb7041Schristos 
227*56bb7041Schristos       if (*s == 0)
228*56bb7041Schristos 	break;
229*56bb7041Schristos 
230*56bb7041Schristos       in_quote = (*s == '\'' || *s == '"');
231*56bb7041Schristos       sep = (in_quote) ? *s++ : ' ';
232*56bb7041Schristos       argv[i++] = s;
233*56bb7041Schristos 
234*56bb7041Schristos       while (*s != sep && *s != 0)
235*56bb7041Schristos 	s++;
236*56bb7041Schristos 
237*56bb7041Schristos       if (*s == 0)
238*56bb7041Schristos 	break;
239*56bb7041Schristos 
240*56bb7041Schristos       *s++ = 0;
241*56bb7041Schristos 
242*56bb7041Schristos       if (in_quote)
243*56bb7041Schristos 	s++;
244*56bb7041Schristos     }
245*56bb7041Schristos   argv[i++] = NULL;
246*56bb7041Schristos 
247*56bb7041Schristos   /* Setup the redirection.  We can't use the usual fork/exec and redirect
248*56bb7041Schristos      since we may be running on non-POSIX Windows host.  */
249*56bb7041Schristos 
250*56bb7041Schristos   fflush (stdout);
251*56bb7041Schristos   fflush (stderr);
252*56bb7041Schristos 
253*56bb7041Schristos   /* Open temporary output file.  */
254*56bb7041Schristos   redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT, 0666);
255*56bb7041Schristos   if (redir_handle == -1)
256*56bb7041Schristos     fatal (_("can't open temporary file `%s': %s"), redir,
257*56bb7041Schristos 	   strerror (errno));
258*56bb7041Schristos 
259*56bb7041Schristos   /* Duplicate the stdout file handle so it can be restored later.  */
260*56bb7041Schristos   stdout_save = dup (STDOUT_FILENO);
261*56bb7041Schristos   if (stdout_save == -1)
262*56bb7041Schristos     fatal (_("can't redirect stdout: `%s': %s"), redir, strerror (errno));
263*56bb7041Schristos 
264*56bb7041Schristos   /* Redirect stdout to our output file.  */
265*56bb7041Schristos   dup2 (redir_handle, STDOUT_FILENO);
266*56bb7041Schristos 
267*56bb7041Schristos   pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
268*56bb7041Schristos 		  &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
269*56bb7041Schristos   free (argv);
270*56bb7041Schristos 
271*56bb7041Schristos   /* Restore stdout to its previous setting.  */
272*56bb7041Schristos   dup2 (stdout_save, STDOUT_FILENO);
273*56bb7041Schristos 
274*56bb7041Schristos   /* Close response file.  */
275*56bb7041Schristos   close (redir_handle);
276*56bb7041Schristos 
277*56bb7041Schristos   if (pid == -1)
278*56bb7041Schristos     {
279*56bb7041Schristos       fatal ("%s %s: %s", errmsg_fmt, errmsg_arg, strerror (errno));
280*56bb7041Schristos       return 1;
281*56bb7041Schristos     }
282*56bb7041Schristos 
283*56bb7041Schristos   retcode = 0;
284*56bb7041Schristos   pid = pwait (pid, &wait_status, 0);
285*56bb7041Schristos 
286*56bb7041Schristos   if (pid == -1)
287*56bb7041Schristos     {
288*56bb7041Schristos       fatal (_("wait: %s"), strerror (errno));
289*56bb7041Schristos       retcode = 1;
290*56bb7041Schristos     }
291*56bb7041Schristos   else if (WIFSIGNALED (wait_status))
292*56bb7041Schristos     {
293*56bb7041Schristos       fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
294*56bb7041Schristos       retcode = 1;
295*56bb7041Schristos     }
296*56bb7041Schristos   else if (WIFEXITED (wait_status))
297*56bb7041Schristos     {
298*56bb7041Schristos       if (WEXITSTATUS (wait_status) != 0)
299*56bb7041Schristos 	{
300*56bb7041Schristos 	  fatal (_("%s exited with status %d"), cmd,
301*56bb7041Schristos 	         WEXITSTATUS (wait_status));
302*56bb7041Schristos 	  retcode = 1;
303*56bb7041Schristos 	}
304*56bb7041Schristos     }
305*56bb7041Schristos   else
306*56bb7041Schristos     retcode = 1;
307*56bb7041Schristos 
308*56bb7041Schristos   return retcode;
309*56bb7041Schristos }
310*56bb7041Schristos 
311*56bb7041Schristos static FILE *
open_input_stream(char * cmd)312*56bb7041Schristos open_input_stream (char *cmd)
313*56bb7041Schristos {
314*56bb7041Schristos   if (istream_type == ISTREAM_FILE)
315*56bb7041Schristos     {
316*56bb7041Schristos       char *fileprefix;
317*56bb7041Schristos 
318*56bb7041Schristos       fileprefix = choose_temp_base ();
319*56bb7041Schristos       cpp_temp_file = (char *) xmalloc (strlen (fileprefix) + 5);
320*56bb7041Schristos       sprintf (cpp_temp_file, "%s.irc", fileprefix);
321*56bb7041Schristos       free (fileprefix);
322*56bb7041Schristos 
323*56bb7041Schristos       if (run_cmd (cmd, cpp_temp_file))
324*56bb7041Schristos 	fatal (_("can't execute `%s': %s"), cmd, strerror (errno));
325*56bb7041Schristos 
326*56bb7041Schristos       cpp_pipe = fopen (cpp_temp_file, FOPEN_RT);
327*56bb7041Schristos       if (cpp_pipe == NULL)
328*56bb7041Schristos 	fatal (_("can't open temporary file `%s': %s"),
329*56bb7041Schristos 	       cpp_temp_file, strerror (errno));
330*56bb7041Schristos 
331*56bb7041Schristos       if (verbose)
332*56bb7041Schristos 	fprintf (stderr,
333*56bb7041Schristos 	         _("Using temporary file `%s' to read preprocessor output\n"),
334*56bb7041Schristos 		 cpp_temp_file);
335*56bb7041Schristos     }
336*56bb7041Schristos   else
337*56bb7041Schristos     {
338*56bb7041Schristos       cpp_pipe = popen (cmd, FOPEN_RT);
339*56bb7041Schristos       if (cpp_pipe == NULL)
340*56bb7041Schristos 	fatal (_("can't popen `%s': %s"), cmd, strerror (errno));
341*56bb7041Schristos       if (verbose)
342*56bb7041Schristos 	fprintf (stderr, _("Using popen to read preprocessor output\n"));
343*56bb7041Schristos     }
344*56bb7041Schristos 
345*56bb7041Schristos   xatexit (close_input_stream);
346*56bb7041Schristos   return cpp_pipe;
347*56bb7041Schristos }
348*56bb7041Schristos 
349*56bb7041Schristos /* Determine if FILENAME contains special characters that
350*56bb7041Schristos    can cause problems unless the entire filename is quoted.  */
351*56bb7041Schristos 
352*56bb7041Schristos static int
filename_need_quotes(const char * filename)353*56bb7041Schristos filename_need_quotes (const char *filename)
354*56bb7041Schristos {
355*56bb7041Schristos   if (filename == NULL || (filename[0] == '-' && filename[1] == 0))
356*56bb7041Schristos     return 0;
357*56bb7041Schristos 
358*56bb7041Schristos   while (*filename != 0)
359*56bb7041Schristos     {
360*56bb7041Schristos       switch (*filename)
361*56bb7041Schristos         {
362*56bb7041Schristos         case '&':
363*56bb7041Schristos         case ' ':
364*56bb7041Schristos         case '<':
365*56bb7041Schristos         case '>':
366*56bb7041Schristos         case '|':
367*56bb7041Schristos         case '%':
368*56bb7041Schristos           return 1;
369*56bb7041Schristos         }
370*56bb7041Schristos       ++filename;
371*56bb7041Schristos     }
372*56bb7041Schristos   return 0;
373*56bb7041Schristos }
374*56bb7041Schristos 
375*56bb7041Schristos /* Look for the preprocessor program.  */
376*56bb7041Schristos 
377*56bb7041Schristos static FILE *
look_for_default(char * cmd,const char * prefix,int end_prefix,const char * preprocargs,const char * filename)378*56bb7041Schristos look_for_default (char *cmd, const char *prefix, int end_prefix,
379*56bb7041Schristos 		  const char *preprocargs, const char *filename)
380*56bb7041Schristos {
381*56bb7041Schristos   char *space;
382*56bb7041Schristos   int found;
383*56bb7041Schristos   struct stat s;
384*56bb7041Schristos   const char *fnquotes = (filename_need_quotes (filename) ? "\"" : "");
385*56bb7041Schristos 
386*56bb7041Schristos   strcpy (cmd, prefix);
387*56bb7041Schristos 
388*56bb7041Schristos   sprintf (cmd + end_prefix, "%s", DEFAULT_PREPROCESSOR);
389*56bb7041Schristos   space = strchr (cmd + end_prefix, ' ');
390*56bb7041Schristos   if (space)
391*56bb7041Schristos     *space = 0;
392*56bb7041Schristos 
393*56bb7041Schristos   if (
394*56bb7041Schristos #if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32)
395*56bb7041Schristos       strchr (cmd, '\\') ||
396*56bb7041Schristos #endif
397*56bb7041Schristos       strchr (cmd, '/'))
398*56bb7041Schristos     {
399*56bb7041Schristos       found = (stat (cmd, &s) == 0
400*56bb7041Schristos #ifdef HAVE_EXECUTABLE_SUFFIX
401*56bb7041Schristos 	       || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
402*56bb7041Schristos #endif
403*56bb7041Schristos 	       );
404*56bb7041Schristos 
405*56bb7041Schristos       if (! found)
406*56bb7041Schristos 	{
407*56bb7041Schristos 	  if (verbose)
408*56bb7041Schristos 	    fprintf (stderr, _("Tried `%s'\n"), cmd);
409*56bb7041Schristos 	  return NULL;
410*56bb7041Schristos 	}
411*56bb7041Schristos     }
412*56bb7041Schristos 
413*56bb7041Schristos   strcpy (cmd, prefix);
414*56bb7041Schristos 
415*56bb7041Schristos   sprintf (cmd + end_prefix, "%s %s %s%s%s",
416*56bb7041Schristos 	   DEFAULT_PREPROCESSOR, preprocargs, fnquotes, filename, fnquotes);
417*56bb7041Schristos 
418*56bb7041Schristos   if (verbose)
419*56bb7041Schristos     fprintf (stderr, _("Using `%s'\n"), cmd);
420*56bb7041Schristos 
421*56bb7041Schristos   cpp_pipe = open_input_stream (cmd);
422*56bb7041Schristos   return cpp_pipe;
423*56bb7041Schristos }
424*56bb7041Schristos 
425*56bb7041Schristos /* Read an rc file.  */
426*56bb7041Schristos 
427*56bb7041Schristos rc_res_directory *
read_rc_file(const char * filename,const char * preprocessor,const char * preprocargs,int language,int use_temp_file)428*56bb7041Schristos read_rc_file (const char *filename, const char *preprocessor,
429*56bb7041Schristos 	      const char *preprocargs, int language, int use_temp_file)
430*56bb7041Schristos {
431*56bb7041Schristos   char *cmd;
432*56bb7041Schristos   const char *fnquotes = (filename_need_quotes (filename) ? "\"" : "");
433*56bb7041Schristos 
434*56bb7041Schristos   if (filename == NULL)
435*56bb7041Schristos     filename = "-";
436*56bb7041Schristos   /* Setup the default resource import path taken from input file.  */
437*56bb7041Schristos   else if (strchr (filename, '/') != NULL || strchr (filename, '\\') != NULL)
438*56bb7041Schristos     {
439*56bb7041Schristos       char *edit, *dir;
440*56bb7041Schristos 
441*56bb7041Schristos       if (filename[0] == '/'
442*56bb7041Schristos 	  || filename[0] == '\\'
443*56bb7041Schristos 	  || filename[1] == ':')
444*56bb7041Schristos         /* Absolute path.  */
445*56bb7041Schristos 	edit = dir = xstrdup (filename);
446*56bb7041Schristos       else
447*56bb7041Schristos 	{
448*56bb7041Schristos 	  /* Relative path.  */
449*56bb7041Schristos 	  edit = dir = xmalloc (strlen (filename) + 3);
450*56bb7041Schristos 	  sprintf (dir, "./%s", filename);
451*56bb7041Schristos 	}
452*56bb7041Schristos 
453*56bb7041Schristos       /* Walk dir backwards stopping at the first directory separator.  */
454*56bb7041Schristos       edit += strlen (dir);
455*56bb7041Schristos       while (edit > dir && (edit[-1] != '\\' && edit[-1] != '/'))
456*56bb7041Schristos 	{
457*56bb7041Schristos 	  --edit;
458*56bb7041Schristos 	  edit[0] = 0;
459*56bb7041Schristos 	}
460*56bb7041Schristos 
461*56bb7041Schristos       /* Cut off trailing slash.  */
462*56bb7041Schristos       --edit;
463*56bb7041Schristos       edit[0] = 0;
464*56bb7041Schristos 
465*56bb7041Schristos       /* Convert all back slashes to forward slashes.  */
466*56bb7041Schristos       while ((edit = strchr (dir, '\\')) != NULL)
467*56bb7041Schristos 	*edit = '/';
468*56bb7041Schristos 
469*56bb7041Schristos       windres_add_include_dir (dir);
470*56bb7041Schristos     }
471*56bb7041Schristos 
472*56bb7041Schristos   istream_type = (use_temp_file) ? ISTREAM_FILE : ISTREAM_PIPE;
473*56bb7041Schristos 
474*56bb7041Schristos   if (preprocargs == NULL)
475*56bb7041Schristos     preprocargs = "";
476*56bb7041Schristos 
477*56bb7041Schristos   if (preprocessor)
478*56bb7041Schristos     {
479*56bb7041Schristos       cmd = xmalloc (strlen (preprocessor)
480*56bb7041Schristos 		     + strlen (preprocargs)
481*56bb7041Schristos 		     + strlen (filename)
482*56bb7041Schristos 		     + strlen (fnquotes) * 2
483*56bb7041Schristos 		     + 10);
484*56bb7041Schristos       sprintf (cmd, "%s %s %s%s%s", preprocessor, preprocargs,
485*56bb7041Schristos 	       fnquotes, filename, fnquotes);
486*56bb7041Schristos 
487*56bb7041Schristos       cpp_pipe = open_input_stream (cmd);
488*56bb7041Schristos     }
489*56bb7041Schristos   else
490*56bb7041Schristos     {
491*56bb7041Schristos       char *dash, *slash, *cp;
492*56bb7041Schristos 
493*56bb7041Schristos       preprocessor = DEFAULT_PREPROCESSOR;
494*56bb7041Schristos 
495*56bb7041Schristos       cmd = xmalloc (strlen (program_name)
496*56bb7041Schristos 		     + strlen (preprocessor)
497*56bb7041Schristos 		     + strlen (preprocargs)
498*56bb7041Schristos 		     + strlen (filename)
499*56bb7041Schristos 		     + strlen (fnquotes) * 2
500*56bb7041Schristos #ifdef HAVE_EXECUTABLE_SUFFIX
501*56bb7041Schristos 		     + strlen (EXECUTABLE_SUFFIX)
502*56bb7041Schristos #endif
503*56bb7041Schristos 		     + 10);
504*56bb7041Schristos 
505*56bb7041Schristos 
506*56bb7041Schristos       dash = slash = 0;
507*56bb7041Schristos       for (cp = program_name; *cp; cp++)
508*56bb7041Schristos 	{
509*56bb7041Schristos 	  if (*cp == '-')
510*56bb7041Schristos 	    dash = cp;
511*56bb7041Schristos 	  if (
512*56bb7041Schristos #if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32)
513*56bb7041Schristos 	      *cp == ':' || *cp == '\\' ||
514*56bb7041Schristos #endif
515*56bb7041Schristos 	      *cp == '/')
516*56bb7041Schristos 	    {
517*56bb7041Schristos 	      slash = cp;
518*56bb7041Schristos 	      dash = 0;
519*56bb7041Schristos 	    }
520*56bb7041Schristos 	}
521*56bb7041Schristos 
522*56bb7041Schristos       cpp_pipe = 0;
523*56bb7041Schristos 
524*56bb7041Schristos       if (dash)
525*56bb7041Schristos 	{
526*56bb7041Schristos 	  /* First, try looking for a prefixed gcc in the windres
527*56bb7041Schristos 	     directory, with the same prefix as windres */
528*56bb7041Schristos 
529*56bb7041Schristos 	  cpp_pipe = look_for_default (cmd, program_name, dash - program_name + 1,
530*56bb7041Schristos 				       preprocargs, filename);
531*56bb7041Schristos 	}
532*56bb7041Schristos 
533*56bb7041Schristos       if (slash && ! cpp_pipe)
534*56bb7041Schristos 	{
535*56bb7041Schristos 	  /* Next, try looking for a gcc in the same directory as
536*56bb7041Schristos              that windres */
537*56bb7041Schristos 
538*56bb7041Schristos 	  cpp_pipe = look_for_default (cmd, program_name, slash - program_name + 1,
539*56bb7041Schristos 				       preprocargs, filename);
540*56bb7041Schristos 	}
541*56bb7041Schristos 
542*56bb7041Schristos       if (! cpp_pipe)
543*56bb7041Schristos 	{
544*56bb7041Schristos 	  /* Sigh, try the default */
545*56bb7041Schristos 
546*56bb7041Schristos 	  cpp_pipe = look_for_default (cmd, "", 0, preprocargs, filename);
547*56bb7041Schristos 	}
548*56bb7041Schristos 
549*56bb7041Schristos     }
550*56bb7041Schristos 
551*56bb7041Schristos   free (cmd);
552*56bb7041Schristos 
553*56bb7041Schristos   rc_filename = xstrdup (filename);
554*56bb7041Schristos   rc_lineno = 1;
555*56bb7041Schristos   if (language != -1)
556*56bb7041Schristos     rcparse_set_language (language);
557*56bb7041Schristos   yyparse ();
558*56bb7041Schristos   rcparse_discard_strings ();
559*56bb7041Schristos 
560*56bb7041Schristos   close_input_stream ();
561*56bb7041Schristos 
562*56bb7041Schristos   if (fontdirs != NULL)
563*56bb7041Schristos     define_fontdirs ();
564*56bb7041Schristos 
565*56bb7041Schristos   free (rc_filename);
566*56bb7041Schristos   rc_filename = NULL;
567*56bb7041Schristos 
568*56bb7041Schristos   return resources;
569*56bb7041Schristos }
570*56bb7041Schristos 
571*56bb7041Schristos /* Close the input stream if it is open.  */
572*56bb7041Schristos 
573*56bb7041Schristos static void
close_input_stream(void)574*56bb7041Schristos close_input_stream (void)
575*56bb7041Schristos {
576*56bb7041Schristos   if (istream_type == ISTREAM_FILE)
577*56bb7041Schristos     {
578*56bb7041Schristos       if (cpp_pipe != NULL)
579*56bb7041Schristos 	fclose (cpp_pipe);
580*56bb7041Schristos 
581*56bb7041Schristos       if (cpp_temp_file != NULL)
582*56bb7041Schristos 	{
583*56bb7041Schristos 	  int errno_save = errno;
584*56bb7041Schristos 
585*56bb7041Schristos 	  unlink (cpp_temp_file);
586*56bb7041Schristos 	  errno = errno_save;
587*56bb7041Schristos 	  free (cpp_temp_file);
588*56bb7041Schristos 	}
589*56bb7041Schristos     }
590*56bb7041Schristos   else
591*56bb7041Schristos     {
592*56bb7041Schristos       if (cpp_pipe != NULL)
593*56bb7041Schristos         {
594*56bb7041Schristos 	  int err;
595*56bb7041Schristos 	  err = pclose (cpp_pipe);
596*56bb7041Schristos 	  /* We are reading from a pipe, therefore we don't
597*56bb7041Schristos              know if cpp failed or succeeded until pclose.  */
598*56bb7041Schristos 	  if (err != 0 || errno == ECHILD)
599*56bb7041Schristos 	    {
600*56bb7041Schristos 	      /* Since this is also run via xatexit, safeguard.  */
601*56bb7041Schristos 	      cpp_pipe = NULL;
602*56bb7041Schristos 	      cpp_temp_file = NULL;
603*56bb7041Schristos 	      fatal (_("preprocessing failed."));
604*56bb7041Schristos 	    }
605*56bb7041Schristos         }
606*56bb7041Schristos     }
607*56bb7041Schristos 
608*56bb7041Schristos   /* Since this is also run via xatexit, safeguard.  */
609*56bb7041Schristos   cpp_pipe = NULL;
610*56bb7041Schristos   cpp_temp_file = NULL;
611*56bb7041Schristos }
612*56bb7041Schristos 
613*56bb7041Schristos /* Report an error while reading an rc file.  */
614*56bb7041Schristos 
615*56bb7041Schristos void
yyerror(const char * msg)616*56bb7041Schristos yyerror (const char *msg)
617*56bb7041Schristos {
618*56bb7041Schristos   fatal ("%s:%d: %s", rc_filename, rc_lineno, msg);
619*56bb7041Schristos }
620*56bb7041Schristos 
621*56bb7041Schristos /* Issue a warning while reading an rc file.  */
622*56bb7041Schristos 
623*56bb7041Schristos void
rcparse_warning(const char * msg)624*56bb7041Schristos rcparse_warning (const char *msg)
625*56bb7041Schristos {
626*56bb7041Schristos   fprintf (stderr, "%s:%d: %s\n", rc_filename, rc_lineno, msg);
627*56bb7041Schristos }
628*56bb7041Schristos 
629*56bb7041Schristos /* Die if we get an unexpected end of file.  */
630*56bb7041Schristos 
631*56bb7041Schristos static void
unexpected_eof(const char * msg)632*56bb7041Schristos unexpected_eof (const char *msg)
633*56bb7041Schristos {
634*56bb7041Schristos   fatal (_("%s: unexpected EOF"), msg);
635*56bb7041Schristos }
636*56bb7041Schristos 
637*56bb7041Schristos /* Read a 16 bit word from a file.  The data is assumed to be little
638*56bb7041Schristos    endian.  */
639*56bb7041Schristos 
640*56bb7041Schristos static int
get_word(FILE * e,const char * msg)641*56bb7041Schristos get_word (FILE *e, const char *msg)
642*56bb7041Schristos {
643*56bb7041Schristos   int b1, b2;
644*56bb7041Schristos 
645*56bb7041Schristos   b1 = getc (e);
646*56bb7041Schristos   b2 = getc (e);
647*56bb7041Schristos   if (feof (e))
648*56bb7041Schristos     unexpected_eof (msg);
649*56bb7041Schristos   return ((b2 & 0xff) << 8) | (b1 & 0xff);
650*56bb7041Schristos }
651*56bb7041Schristos 
652*56bb7041Schristos /* Read a 32 bit word from a file.  The data is assumed to be little
653*56bb7041Schristos    endian.  */
654*56bb7041Schristos 
655*56bb7041Schristos static unsigned long
get_long(FILE * e,const char * msg)656*56bb7041Schristos get_long (FILE *e, const char *msg)
657*56bb7041Schristos {
658*56bb7041Schristos   int b1, b2, b3, b4;
659*56bb7041Schristos 
660*56bb7041Schristos   b1 = getc (e);
661*56bb7041Schristos   b2 = getc (e);
662*56bb7041Schristos   b3 = getc (e);
663*56bb7041Schristos   b4 = getc (e);
664*56bb7041Schristos   if (feof (e))
665*56bb7041Schristos     unexpected_eof (msg);
666*56bb7041Schristos   return (((((((b4 & 0xff) << 8)
667*56bb7041Schristos 	      | (b3 & 0xff)) << 8)
668*56bb7041Schristos 	    | (b2 & 0xff)) << 8)
669*56bb7041Schristos 	  | (b1 & 0xff));
670*56bb7041Schristos }
671*56bb7041Schristos 
672*56bb7041Schristos /* Read data from a file.  This is a wrapper to do error checking.  */
673*56bb7041Schristos 
674*56bb7041Schristos static void
get_data(FILE * e,bfd_byte * p,rc_uint_type c,const char * msg)675*56bb7041Schristos get_data (FILE *e, bfd_byte *p, rc_uint_type c, const char *msg)
676*56bb7041Schristos {
677*56bb7041Schristos   rc_uint_type got; /* $$$d */
678*56bb7041Schristos 
679*56bb7041Schristos   got = (rc_uint_type) fread (p, 1, c, e);
680*56bb7041Schristos   if (got == c)
681*56bb7041Schristos     return;
682*56bb7041Schristos 
683*56bb7041Schristos   fatal (_("%s: read of %lu returned %lu"),
684*56bb7041Schristos 	 msg, (unsigned long) c, (unsigned long) got);
685*56bb7041Schristos }
686*56bb7041Schristos 
687*56bb7041Schristos /* Define an accelerator resource.  */
688*56bb7041Schristos 
689*56bb7041Schristos void
define_accelerator(rc_res_id id,const rc_res_res_info * resinfo,rc_accelerator * data)690*56bb7041Schristos define_accelerator (rc_res_id id, const rc_res_res_info *resinfo,
691*56bb7041Schristos 		    rc_accelerator *data)
692*56bb7041Schristos {
693*56bb7041Schristos   rc_res_resource *r;
694*56bb7041Schristos 
695*56bb7041Schristos   r = define_standard_resource (&resources, RT_ACCELERATOR, id,
696*56bb7041Schristos 				resinfo->language, 0);
697*56bb7041Schristos   r->type = RES_TYPE_ACCELERATOR;
698*56bb7041Schristos   r->u.acc = data;
699*56bb7041Schristos   r->res_info = *resinfo;
700*56bb7041Schristos }
701*56bb7041Schristos 
702*56bb7041Schristos /* Define a bitmap resource.  Bitmap data is stored in a file.  The
703*56bb7041Schristos    first 14 bytes of the file are a standard header, which is not
704*56bb7041Schristos    included in the resource data.  */
705*56bb7041Schristos 
706*56bb7041Schristos #define BITMAP_SKIP (14)
707*56bb7041Schristos 
708*56bb7041Schristos void
define_bitmap(rc_res_id id,const rc_res_res_info * resinfo,const char * filename)709*56bb7041Schristos define_bitmap (rc_res_id id, const rc_res_res_info *resinfo,
710*56bb7041Schristos 	       const char *filename)
711*56bb7041Schristos {
712*56bb7041Schristos   FILE *e;
713*56bb7041Schristos   char *real_filename;
714*56bb7041Schristos   struct stat s;
715*56bb7041Schristos   bfd_byte *data;
716*56bb7041Schristos   rc_uint_type i;
717*56bb7041Schristos   rc_res_resource *r;
718*56bb7041Schristos 
719*56bb7041Schristos   e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename);
720*56bb7041Schristos 
721*56bb7041Schristos   if (stat (real_filename, &s) < 0)
722*56bb7041Schristos     fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
723*56bb7041Schristos 	   strerror (errno));
724*56bb7041Schristos 
725*56bb7041Schristos   data = (bfd_byte *) res_alloc (s.st_size - BITMAP_SKIP);
726*56bb7041Schristos 
727*56bb7041Schristos   for (i = 0; i < BITMAP_SKIP; i++)
728*56bb7041Schristos     getc (e);
729*56bb7041Schristos 
730*56bb7041Schristos   get_data (e, data, s.st_size - BITMAP_SKIP, real_filename);
731*56bb7041Schristos 
732*56bb7041Schristos   fclose (e);
733*56bb7041Schristos   free (real_filename);
734*56bb7041Schristos 
735*56bb7041Schristos   r = define_standard_resource (&resources, RT_BITMAP, id,
736*56bb7041Schristos 				resinfo->language, 0);
737*56bb7041Schristos 
738*56bb7041Schristos   r->type = RES_TYPE_BITMAP;
739*56bb7041Schristos   r->u.data.length = s.st_size - BITMAP_SKIP;
740*56bb7041Schristos   r->u.data.data = data;
741*56bb7041Schristos   r->res_info = *resinfo;
742*56bb7041Schristos }
743*56bb7041Schristos 
744*56bb7041Schristos /* Define a cursor resource.  A cursor file may contain a set of
745*56bb7041Schristos    bitmaps, each representing the same cursor at various different
746*56bb7041Schristos    resolutions.  They each get written out with a different ID.  The
747*56bb7041Schristos    real cursor resource is then a group resource which can be used to
748*56bb7041Schristos    select one of the actual cursors.  */
749*56bb7041Schristos 
750*56bb7041Schristos void
define_cursor(rc_res_id id,const rc_res_res_info * resinfo,const char * filename)751*56bb7041Schristos define_cursor (rc_res_id id, const rc_res_res_info *resinfo,
752*56bb7041Schristos 	       const char *filename)
753*56bb7041Schristos {
754*56bb7041Schristos   FILE *e;
755*56bb7041Schristos   char *real_filename;
756*56bb7041Schristos   int type, count, i;
757*56bb7041Schristos   struct icondir *icondirs;
758*56bb7041Schristos   int first_cursor;
759*56bb7041Schristos   rc_res_resource *r;
760*56bb7041Schristos   rc_group_cursor *first, **pp;
761*56bb7041Schristos 
762*56bb7041Schristos   e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename);
763*56bb7041Schristos 
764*56bb7041Schristos   /* A cursor file is basically an icon file.  The start of the file
765*56bb7041Schristos      is a three word structure.  The first word is ignored.  The
766*56bb7041Schristos      second word is the type of data.  The third word is the number of
767*56bb7041Schristos      entries.  */
768*56bb7041Schristos 
769*56bb7041Schristos   get_word (e, real_filename);
770*56bb7041Schristos   type = get_word (e, real_filename);
771*56bb7041Schristos   count = get_word (e, real_filename);
772*56bb7041Schristos   if (type != 2)
773*56bb7041Schristos     fatal (_("cursor file `%s' does not contain cursor data"), real_filename);
774*56bb7041Schristos 
775*56bb7041Schristos   /* Read in the icon directory entries.  */
776*56bb7041Schristos 
777*56bb7041Schristos   icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
778*56bb7041Schristos 
779*56bb7041Schristos   for (i = 0; i < count; i++)
780*56bb7041Schristos     {
781*56bb7041Schristos       icondirs[i].width = getc (e);
782*56bb7041Schristos       icondirs[i].height = getc (e);
783*56bb7041Schristos       icondirs[i].colorcount = getc (e);
784*56bb7041Schristos       getc (e);
785*56bb7041Schristos       icondirs[i].u.cursor.xhotspot = get_word (e, real_filename);
786*56bb7041Schristos       icondirs[i].u.cursor.yhotspot = get_word (e, real_filename);
787*56bb7041Schristos       icondirs[i].bytes = get_long (e, real_filename);
788*56bb7041Schristos       icondirs[i].offset = get_long (e, real_filename);
789*56bb7041Schristos 
790*56bb7041Schristos       if (feof (e))
791*56bb7041Schristos 	unexpected_eof (real_filename);
792*56bb7041Schristos     }
793*56bb7041Schristos 
794*56bb7041Schristos   /* Define each cursor as a unique resource.  */
795*56bb7041Schristos 
796*56bb7041Schristos   first_cursor = cursors;
797*56bb7041Schristos 
798*56bb7041Schristos   for (i = 0; i < count; i++)
799*56bb7041Schristos     {
800*56bb7041Schristos       bfd_byte *data;
801*56bb7041Schristos       rc_res_id name;
802*56bb7041Schristos       rc_cursor *c;
803*56bb7041Schristos 
804*56bb7041Schristos       if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
805*56bb7041Schristos 	fatal (_("%s: fseek to %lu failed: %s"), real_filename,
806*56bb7041Schristos 	       icondirs[i].offset, strerror (errno));
807*56bb7041Schristos 
808*56bb7041Schristos       data = (bfd_byte *) res_alloc (icondirs[i].bytes);
809*56bb7041Schristos 
810*56bb7041Schristos       get_data (e, data, icondirs[i].bytes, real_filename);
811*56bb7041Schristos 
812*56bb7041Schristos       c = (rc_cursor *) res_alloc (sizeof (rc_cursor));
813*56bb7041Schristos       c->xhotspot = icondirs[i].u.cursor.xhotspot;
814*56bb7041Schristos       c->yhotspot = icondirs[i].u.cursor.yhotspot;
815*56bb7041Schristos       c->length = icondirs[i].bytes;
816*56bb7041Schristos       c->data = data;
817*56bb7041Schristos 
818*56bb7041Schristos       ++cursors;
819*56bb7041Schristos 
820*56bb7041Schristos       name.named = 0;
821*56bb7041Schristos       name.u.id = cursors;
822*56bb7041Schristos 
823*56bb7041Schristos       r = define_standard_resource (&resources, RT_CURSOR, name,
824*56bb7041Schristos 				    resinfo->language, 0);
825*56bb7041Schristos       r->type = RES_TYPE_CURSOR;
826*56bb7041Schristos       r->u.cursor = c;
827*56bb7041Schristos       r->res_info = *resinfo;
828*56bb7041Schristos     }
829*56bb7041Schristos 
830*56bb7041Schristos   fclose (e);
831*56bb7041Schristos   free (real_filename);
832*56bb7041Schristos 
833*56bb7041Schristos   /* Define a cursor group resource.  */
834*56bb7041Schristos 
835*56bb7041Schristos   first = NULL;
836*56bb7041Schristos   pp = &first;
837*56bb7041Schristos   for (i = 0; i < count; i++)
838*56bb7041Schristos     {
839*56bb7041Schristos       rc_group_cursor *cg;
840*56bb7041Schristos 
841*56bb7041Schristos       cg = (rc_group_cursor *) res_alloc (sizeof (rc_group_cursor));
842*56bb7041Schristos       cg->next = NULL;
843*56bb7041Schristos       cg->width = icondirs[i].width;
844*56bb7041Schristos       cg->height = 2 * icondirs[i].height;
845*56bb7041Schristos 
846*56bb7041Schristos       /* FIXME: What should these be set to?  */
847*56bb7041Schristos       cg->planes = 1;
848*56bb7041Schristos       cg->bits = 1;
849*56bb7041Schristos 
850*56bb7041Schristos       cg->bytes = icondirs[i].bytes + 4;
851*56bb7041Schristos       cg->index = first_cursor + i + 1;
852*56bb7041Schristos 
853*56bb7041Schristos       *pp = cg;
854*56bb7041Schristos       pp = &(*pp)->next;
855*56bb7041Schristos     }
856*56bb7041Schristos 
857*56bb7041Schristos   free (icondirs);
858*56bb7041Schristos 
859*56bb7041Schristos   r = define_standard_resource (&resources, RT_GROUP_CURSOR, id,
860*56bb7041Schristos 				resinfo->language, 0);
861*56bb7041Schristos   r->type = RES_TYPE_GROUP_CURSOR;
862*56bb7041Schristos   r->u.group_cursor = first;
863*56bb7041Schristos   r->res_info = *resinfo;
864*56bb7041Schristos }
865*56bb7041Schristos 
866*56bb7041Schristos /* Define a dialog resource.  */
867*56bb7041Schristos 
868*56bb7041Schristos void
define_dialog(rc_res_id id,const rc_res_res_info * resinfo,const rc_dialog * dialog)869*56bb7041Schristos define_dialog (rc_res_id id, const rc_res_res_info *resinfo,
870*56bb7041Schristos 	       const rc_dialog *dialog)
871*56bb7041Schristos {
872*56bb7041Schristos   rc_dialog *copy;
873*56bb7041Schristos   rc_res_resource *r;
874*56bb7041Schristos 
875*56bb7041Schristos   copy = (rc_dialog *) res_alloc (sizeof *copy);
876*56bb7041Schristos   *copy = *dialog;
877*56bb7041Schristos 
878*56bb7041Schristos   r = define_standard_resource (&resources, RT_DIALOG, id,
879*56bb7041Schristos 				resinfo->language, 0);
880*56bb7041Schristos   r->type = RES_TYPE_DIALOG;
881*56bb7041Schristos   r->u.dialog = copy;
882*56bb7041Schristos   r->res_info = *resinfo;
883*56bb7041Schristos }
884*56bb7041Schristos 
885*56bb7041Schristos /* Define a dialog control.  This does not define a resource, but
886*56bb7041Schristos    merely allocates and fills in a structure.  */
887*56bb7041Schristos 
888*56bb7041Schristos rc_dialog_control *
define_control(const rc_res_id iid,rc_uint_type id,rc_uint_type x,rc_uint_type y,rc_uint_type width,rc_uint_type height,const rc_res_id class,rc_uint_type style,rc_uint_type exstyle)889*56bb7041Schristos define_control (const rc_res_id iid, rc_uint_type id, rc_uint_type x,
890*56bb7041Schristos 		rc_uint_type y, rc_uint_type width, rc_uint_type height,
891*56bb7041Schristos 		const rc_res_id class, rc_uint_type style,
892*56bb7041Schristos 		rc_uint_type exstyle)
893*56bb7041Schristos {
894*56bb7041Schristos   rc_dialog_control *n;
895*56bb7041Schristos 
896*56bb7041Schristos   n = (rc_dialog_control *) res_alloc (sizeof (rc_dialog_control));
897*56bb7041Schristos   n->next = NULL;
898*56bb7041Schristos   n->id = id;
899*56bb7041Schristos   n->style = style;
900*56bb7041Schristos   n->exstyle = exstyle;
901*56bb7041Schristos   n->x = x;
902*56bb7041Schristos   n->y = y;
903*56bb7041Schristos   n->width = width;
904*56bb7041Schristos   n->height = height;
905*56bb7041Schristos   n->class = class;
906*56bb7041Schristos   n->text = iid;
907*56bb7041Schristos   n->data = NULL;
908*56bb7041Schristos   n->help = 0;
909*56bb7041Schristos 
910*56bb7041Schristos   return n;
911*56bb7041Schristos }
912*56bb7041Schristos 
913*56bb7041Schristos rc_dialog_control *
define_icon_control(rc_res_id iid,rc_uint_type id,rc_uint_type x,rc_uint_type y,rc_uint_type style,rc_uint_type exstyle,rc_uint_type help,rc_rcdata_item * data,rc_dialog_ex * ex)914*56bb7041Schristos define_icon_control (rc_res_id iid, rc_uint_type id, rc_uint_type x,
915*56bb7041Schristos 		     rc_uint_type y, rc_uint_type style,
916*56bb7041Schristos 		     rc_uint_type exstyle, rc_uint_type help,
917*56bb7041Schristos 		     rc_rcdata_item *data, rc_dialog_ex *ex)
918*56bb7041Schristos {
919*56bb7041Schristos   rc_dialog_control *n;
920*56bb7041Schristos   rc_res_id tid;
921*56bb7041Schristos   rc_res_id cid;
922*56bb7041Schristos 
923*56bb7041Schristos   if (style == 0)
924*56bb7041Schristos     style = SS_ICON | WS_CHILD | WS_VISIBLE;
925*56bb7041Schristos   res_string_to_id (&tid, "");
926*56bb7041Schristos   cid.named = 0;
927*56bb7041Schristos   cid.u.id = CTL_STATIC;
928*56bb7041Schristos   n = define_control (tid, id, x, y, 0, 0, cid, style, exstyle);
929*56bb7041Schristos   n->text = iid;
930*56bb7041Schristos   if (help && ! ex)
931*56bb7041Schristos     rcparse_warning (_("help ID requires DIALOGEX"));
932*56bb7041Schristos   if (data && ! ex)
933*56bb7041Schristos     rcparse_warning (_("control data requires DIALOGEX"));
934*56bb7041Schristos   n->help = help;
935*56bb7041Schristos   n->data = data;
936*56bb7041Schristos 
937*56bb7041Schristos   return n;
938*56bb7041Schristos }
939*56bb7041Schristos 
940*56bb7041Schristos /* Define a font resource.  */
941*56bb7041Schristos 
942*56bb7041Schristos void
define_font(rc_res_id id,const rc_res_res_info * resinfo,const char * filename)943*56bb7041Schristos define_font (rc_res_id id, const rc_res_res_info *resinfo,
944*56bb7041Schristos 	     const char *filename)
945*56bb7041Schristos {
946*56bb7041Schristos   FILE *e;
947*56bb7041Schristos   char *real_filename;
948*56bb7041Schristos   struct stat s;
949*56bb7041Schristos   bfd_byte *data;
950*56bb7041Schristos   rc_res_resource *r;
951*56bb7041Schristos   long offset;
952*56bb7041Schristos   long fontdatalength;
953*56bb7041Schristos   bfd_byte *fontdata;
954*56bb7041Schristos   rc_fontdir *fd;
955*56bb7041Schristos   const char *device, *face;
956*56bb7041Schristos   rc_fontdir **pp;
957*56bb7041Schristos 
958*56bb7041Schristos   e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
959*56bb7041Schristos 
960*56bb7041Schristos   if (stat (real_filename, &s) < 0)
961*56bb7041Schristos     fatal (_("stat failed on font file `%s': %s"), real_filename,
962*56bb7041Schristos 	   strerror (errno));
963*56bb7041Schristos 
964*56bb7041Schristos   data = (bfd_byte *) res_alloc (s.st_size);
965*56bb7041Schristos 
966*56bb7041Schristos   get_data (e, data, s.st_size, real_filename);
967*56bb7041Schristos 
968*56bb7041Schristos   fclose (e);
969*56bb7041Schristos   free (real_filename);
970*56bb7041Schristos 
971*56bb7041Schristos   r = define_standard_resource (&resources, RT_FONT, id,
972*56bb7041Schristos 				resinfo->language, 0);
973*56bb7041Schristos 
974*56bb7041Schristos   r->type = RES_TYPE_FONT;
975*56bb7041Schristos   r->u.data.length = s.st_size;
976*56bb7041Schristos   r->u.data.data = data;
977*56bb7041Schristos   r->res_info = *resinfo;
978*56bb7041Schristos 
979*56bb7041Schristos   /* For each font resource, we must add an entry in the FONTDIR
980*56bb7041Schristos      resource.  The FONTDIR resource includes some strings in the font
981*56bb7041Schristos      file.  To find them, we have to do some magic on the data we have
982*56bb7041Schristos      read.  */
983*56bb7041Schristos 
984*56bb7041Schristos   offset = ((((((data[47] << 8)
985*56bb7041Schristos 		| data[46]) << 8)
986*56bb7041Schristos 	      | data[45]) << 8)
987*56bb7041Schristos 	    | data[44]);
988*56bb7041Schristos   if (offset > 0 && offset < s.st_size)
989*56bb7041Schristos     device = (char *) data + offset;
990*56bb7041Schristos   else
991*56bb7041Schristos     device = "";
992*56bb7041Schristos 
993*56bb7041Schristos   offset = ((((((data[51] << 8)
994*56bb7041Schristos 		| data[50]) << 8)
995*56bb7041Schristos 	      | data[49]) << 8)
996*56bb7041Schristos 	    | data[48]);
997*56bb7041Schristos   if (offset > 0 && offset < s.st_size)
998*56bb7041Schristos     face = (char *) data + offset;
999*56bb7041Schristos   else
1000*56bb7041Schristos     face = "";
1001*56bb7041Schristos 
1002*56bb7041Schristos   ++fonts;
1003*56bb7041Schristos 
1004*56bb7041Schristos   fontdatalength = 58 + strlen (device) + strlen (face);
1005*56bb7041Schristos   fontdata = (bfd_byte *) res_alloc (fontdatalength);
1006*56bb7041Schristos   memcpy (fontdata, data, 56);
1007*56bb7041Schristos   strcpy ((char *) fontdata + 56, device);
1008*56bb7041Schristos   strcpy ((char *) fontdata + 57 + strlen (device), face);
1009*56bb7041Schristos 
1010*56bb7041Schristos   fd = (rc_fontdir *) res_alloc (sizeof (rc_fontdir));
1011*56bb7041Schristos   fd->next = NULL;
1012*56bb7041Schristos   fd->index = fonts;
1013*56bb7041Schristos   fd->length = fontdatalength;
1014*56bb7041Schristos   fd->data = fontdata;
1015*56bb7041Schristos 
1016*56bb7041Schristos   for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next)
1017*56bb7041Schristos     ;
1018*56bb7041Schristos   *pp = fd;
1019*56bb7041Schristos 
1020*56bb7041Schristos   /* For the single fontdirs resource, we always use the resource
1021*56bb7041Schristos      information of the last font.  I don't know what else to do.  */
1022*56bb7041Schristos   fontdirs_resinfo = *resinfo;
1023*56bb7041Schristos }
1024*56bb7041Schristos 
1025*56bb7041Schristos static void
define_font_rcdata(rc_res_id id,const rc_res_res_info * resinfo,rc_rcdata_item * data)1026*56bb7041Schristos define_font_rcdata (rc_res_id id,const rc_res_res_info *resinfo,
1027*56bb7041Schristos 		    rc_rcdata_item *data)
1028*56bb7041Schristos {
1029*56bb7041Schristos   rc_res_resource *r;
1030*56bb7041Schristos   rc_uint_type len_data;
1031*56bb7041Schristos   bfd_byte *pb_data;
1032*56bb7041Schristos 
1033*56bb7041Schristos   r = define_standard_resource (&resources, RT_FONT, id,
1034*56bb7041Schristos 				resinfo->language, 0);
1035*56bb7041Schristos 
1036*56bb7041Schristos   pb_data = rcdata_render_as_buffer (data, &len_data);
1037*56bb7041Schristos 
1038*56bb7041Schristos   r->type = RES_TYPE_FONT;
1039*56bb7041Schristos   r->u.data.length = len_data;
1040*56bb7041Schristos   r->u.data.data = pb_data;
1041*56bb7041Schristos   r->res_info = *resinfo;
1042*56bb7041Schristos }
1043*56bb7041Schristos 
1044*56bb7041Schristos /* Define the fontdirs resource.  This is called after the entire rc
1045*56bb7041Schristos    file has been parsed, if any font resources were seen.  */
1046*56bb7041Schristos 
1047*56bb7041Schristos static void
define_fontdirs(void)1048*56bb7041Schristos define_fontdirs (void)
1049*56bb7041Schristos {
1050*56bb7041Schristos   rc_res_resource *r;
1051*56bb7041Schristos   rc_res_id id;
1052*56bb7041Schristos 
1053*56bb7041Schristos   id.named = 0;
1054*56bb7041Schristos   id.u.id = 1;
1055*56bb7041Schristos 
1056*56bb7041Schristos   r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
1057*56bb7041Schristos 
1058*56bb7041Schristos   r->type = RES_TYPE_FONTDIR;
1059*56bb7041Schristos   r->u.fontdir = fontdirs;
1060*56bb7041Schristos   r->res_info = fontdirs_resinfo;
1061*56bb7041Schristos }
1062*56bb7041Schristos 
1063*56bb7041Schristos static bfd_byte *
rcdata_render_as_buffer(const rc_rcdata_item * data,rc_uint_type * plen)1064*56bb7041Schristos rcdata_render_as_buffer (const rc_rcdata_item *data, rc_uint_type *plen)
1065*56bb7041Schristos {
1066*56bb7041Schristos   const rc_rcdata_item *d;
1067*56bb7041Schristos   bfd_byte *ret = NULL, *pret;
1068*56bb7041Schristos   rc_uint_type len = 0;
1069*56bb7041Schristos 
1070*56bb7041Schristos   for (d = data; d != NULL; d = d->next)
1071*56bb7041Schristos     len += rcdata_copy (d, NULL);
1072*56bb7041Schristos   if (len != 0)
1073*56bb7041Schristos     {
1074*56bb7041Schristos       ret = pret = (bfd_byte *) res_alloc (len);
1075*56bb7041Schristos       for (d = data; d != NULL; d = d->next)
1076*56bb7041Schristos 	pret += rcdata_copy (d, pret);
1077*56bb7041Schristos     }
1078*56bb7041Schristos   if (plen)
1079*56bb7041Schristos     *plen = len;
1080*56bb7041Schristos   return ret;
1081*56bb7041Schristos }
1082*56bb7041Schristos 
1083*56bb7041Schristos static void
define_fontdir_rcdata(rc_res_id id,const rc_res_res_info * resinfo,rc_rcdata_item * data)1084*56bb7041Schristos define_fontdir_rcdata (rc_res_id id,const rc_res_res_info *resinfo,
1085*56bb7041Schristos 		       rc_rcdata_item *data)
1086*56bb7041Schristos {
1087*56bb7041Schristos   rc_res_resource *r;
1088*56bb7041Schristos   rc_fontdir *fd, *fd_first, *fd_cur;
1089*56bb7041Schristos   rc_uint_type len_data;
1090*56bb7041Schristos   bfd_byte *pb_data;
1091*56bb7041Schristos   rc_uint_type c;
1092*56bb7041Schristos 
1093*56bb7041Schristos   fd_cur = fd_first = NULL;
1094*56bb7041Schristos   r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
1095*56bb7041Schristos 
1096*56bb7041Schristos   pb_data = rcdata_render_as_buffer (data, &len_data);
1097*56bb7041Schristos 
1098*56bb7041Schristos   if (pb_data)
1099*56bb7041Schristos     {
1100*56bb7041Schristos       rc_uint_type off = 2;
1101*56bb7041Schristos       c = windres_get_16 (&wrtarget, pb_data, len_data);
1102*56bb7041Schristos       for (; c > 0; c--)
1103*56bb7041Schristos 	{
1104*56bb7041Schristos 	  size_t len;
1105*56bb7041Schristos 	  rc_uint_type safe_pos = off;
1106*56bb7041Schristos 	  const struct bin_fontdir_item *bfi;
1107*56bb7041Schristos 
1108*56bb7041Schristos 	  bfi = (const struct bin_fontdir_item *) pb_data + off;
1109*56bb7041Schristos 	  fd = (rc_fontdir *) res_alloc (sizeof (rc_fontdir));
1110*56bb7041Schristos 	  fd->index = windres_get_16 (&wrtarget, bfi->index, len_data - off);
1111*56bb7041Schristos 	  fd->data = pb_data + off;
1112*56bb7041Schristos 	  off += 56;
1113*56bb7041Schristos 	  len = strlen ((char *) bfi->device_name) + 1;
1114*56bb7041Schristos 	  off += (rc_uint_type) len;
1115*56bb7041Schristos 	  off += (rc_uint_type) strlen ((char *) bfi->device_name + len) + 1;
1116*56bb7041Schristos 	  fd->length = (off - safe_pos);
1117*56bb7041Schristos 	  fd->next = NULL;
1118*56bb7041Schristos 	  if (fd_first == NULL)
1119*56bb7041Schristos 	    fd_first = fd;
1120*56bb7041Schristos 	  else
1121*56bb7041Schristos 	    fd_cur->next = fd;
1122*56bb7041Schristos 	  fd_cur = fd;
1123*56bb7041Schristos 	}
1124*56bb7041Schristos     }
1125*56bb7041Schristos   r->type = RES_TYPE_FONTDIR;
1126*56bb7041Schristos   r->u.fontdir = fd_first;
1127*56bb7041Schristos   r->res_info = *resinfo;
1128*56bb7041Schristos }
1129*56bb7041Schristos 
define_messagetable_rcdata(rc_res_id id,const rc_res_res_info * resinfo,rc_rcdata_item * data)1130*56bb7041Schristos static void define_messagetable_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
1131*56bb7041Schristos 					rc_rcdata_item *data)
1132*56bb7041Schristos {
1133*56bb7041Schristos   rc_res_resource *r;
1134*56bb7041Schristos   rc_uint_type len_data;
1135*56bb7041Schristos   bfd_byte *pb_data;
1136*56bb7041Schristos 
1137*56bb7041Schristos   r = define_standard_resource (&resources, RT_MESSAGETABLE, id, resinfo->language, 0);
1138*56bb7041Schristos 
1139*56bb7041Schristos   pb_data = rcdata_render_as_buffer (data, &len_data);
1140*56bb7041Schristos   r->type = RES_TYPE_MESSAGETABLE;
1141*56bb7041Schristos   r->u.data.length = len_data;
1142*56bb7041Schristos   r->u.data.data = pb_data;
1143*56bb7041Schristos   r->res_info = *resinfo;
1144*56bb7041Schristos }
1145*56bb7041Schristos 
1146*56bb7041Schristos /* Define an icon resource.  An icon file may contain a set of
1147*56bb7041Schristos    bitmaps, each representing the same icon at various different
1148*56bb7041Schristos    resolutions.  They each get written out with a different ID.  The
1149*56bb7041Schristos    real icon resource is then a group resource which can be used to
1150*56bb7041Schristos    select one of the actual icon bitmaps.  */
1151*56bb7041Schristos 
1152*56bb7041Schristos void
define_icon(rc_res_id id,const rc_res_res_info * resinfo,const char * filename)1153*56bb7041Schristos define_icon (rc_res_id id, const rc_res_res_info *resinfo,
1154*56bb7041Schristos 	     const char *filename)
1155*56bb7041Schristos {
1156*56bb7041Schristos   FILE *e;
1157*56bb7041Schristos   char *real_filename;
1158*56bb7041Schristos   int type, count, i;
1159*56bb7041Schristos   struct icondir *icondirs;
1160*56bb7041Schristos   int first_icon;
1161*56bb7041Schristos   rc_res_resource *r;
1162*56bb7041Schristos   rc_group_icon *first, **pp;
1163*56bb7041Schristos 
1164*56bb7041Schristos   e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename);
1165*56bb7041Schristos 
1166*56bb7041Schristos   /* The start of an icon file is a three word structure.  The first
1167*56bb7041Schristos      word is ignored.  The second word is the type of data.  The third
1168*56bb7041Schristos      word is the number of entries.  */
1169*56bb7041Schristos 
1170*56bb7041Schristos   get_word (e, real_filename);
1171*56bb7041Schristos   type = get_word (e, real_filename);
1172*56bb7041Schristos   count = get_word (e, real_filename);
1173*56bb7041Schristos   if (type != 1)
1174*56bb7041Schristos     fatal (_("icon file `%s' does not contain icon data"), real_filename);
1175*56bb7041Schristos 
1176*56bb7041Schristos   /* Read in the icon directory entries.  */
1177*56bb7041Schristos 
1178*56bb7041Schristos   icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
1179*56bb7041Schristos 
1180*56bb7041Schristos   for (i = 0; i < count; i++)
1181*56bb7041Schristos     {
1182*56bb7041Schristos       icondirs[i].width = getc (e);
1183*56bb7041Schristos       icondirs[i].height = getc (e);
1184*56bb7041Schristos       icondirs[i].colorcount = getc (e);
1185*56bb7041Schristos       getc (e);
1186*56bb7041Schristos       icondirs[i].u.icon.planes = get_word (e, real_filename);
1187*56bb7041Schristos       icondirs[i].u.icon.bits = get_word (e, real_filename);
1188*56bb7041Schristos       icondirs[i].bytes = get_long (e, real_filename);
1189*56bb7041Schristos       icondirs[i].offset = get_long (e, real_filename);
1190*56bb7041Schristos 
1191*56bb7041Schristos       if (feof (e))
1192*56bb7041Schristos 	unexpected_eof (real_filename);
1193*56bb7041Schristos     }
1194*56bb7041Schristos 
1195*56bb7041Schristos   /* Define each icon as a unique resource.  */
1196*56bb7041Schristos 
1197*56bb7041Schristos   first_icon = icons;
1198*56bb7041Schristos 
1199*56bb7041Schristos   for (i = 0; i < count; i++)
1200*56bb7041Schristos     {
1201*56bb7041Schristos       bfd_byte *data;
1202*56bb7041Schristos       rc_res_id name;
1203*56bb7041Schristos 
1204*56bb7041Schristos       if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
1205*56bb7041Schristos 	fatal (_("%s: fseek to %lu failed: %s"), real_filename,
1206*56bb7041Schristos 	       icondirs[i].offset, strerror (errno));
1207*56bb7041Schristos 
1208*56bb7041Schristos       data = (bfd_byte *) res_alloc (icondirs[i].bytes);
1209*56bb7041Schristos 
1210*56bb7041Schristos       get_data (e, data, icondirs[i].bytes, real_filename);
1211*56bb7041Schristos 
1212*56bb7041Schristos       ++icons;
1213*56bb7041Schristos 
1214*56bb7041Schristos       name.named = 0;
1215*56bb7041Schristos       name.u.id = icons;
1216*56bb7041Schristos 
1217*56bb7041Schristos       r = define_standard_resource (&resources, RT_ICON, name,
1218*56bb7041Schristos 				    resinfo->language, 0);
1219*56bb7041Schristos       r->type = RES_TYPE_ICON;
1220*56bb7041Schristos       r->u.data.length = icondirs[i].bytes;
1221*56bb7041Schristos       r->u.data.data = data;
1222*56bb7041Schristos       r->res_info = *resinfo;
1223*56bb7041Schristos     }
1224*56bb7041Schristos 
1225*56bb7041Schristos   fclose (e);
1226*56bb7041Schristos   free (real_filename);
1227*56bb7041Schristos 
1228*56bb7041Schristos   /* Define an icon group resource.  */
1229*56bb7041Schristos 
1230*56bb7041Schristos   first = NULL;
1231*56bb7041Schristos   pp = &first;
1232*56bb7041Schristos   for (i = 0; i < count; i++)
1233*56bb7041Schristos     {
1234*56bb7041Schristos       rc_group_icon *cg;
1235*56bb7041Schristos 
1236*56bb7041Schristos       /* For some reason, at least in some files the planes and bits
1237*56bb7041Schristos          are zero.  We instead set them from the color.  This is
1238*56bb7041Schristos          copied from rcl.  */
1239*56bb7041Schristos 
1240*56bb7041Schristos       cg = (rc_group_icon *) res_alloc (sizeof (rc_group_icon));
1241*56bb7041Schristos       cg->next = NULL;
1242*56bb7041Schristos       cg->width = icondirs[i].width;
1243*56bb7041Schristos       cg->height = icondirs[i].height;
1244*56bb7041Schristos       cg->colors = icondirs[i].colorcount;
1245*56bb7041Schristos 
1246*56bb7041Schristos       if (icondirs[i].u.icon.planes)
1247*56bb7041Schristos 	cg->planes = icondirs[i].u.icon.planes;
1248*56bb7041Schristos       else
1249*56bb7041Schristos 	cg->planes = 1;
1250*56bb7041Schristos 
1251*56bb7041Schristos       if (icondirs[i].u.icon.bits)
1252*56bb7041Schristos 	cg->bits = icondirs[i].u.icon.bits;
1253*56bb7041Schristos       else
1254*56bb7041Schristos 	{
1255*56bb7041Schristos 	  cg->bits = 0;
1256*56bb7041Schristos 
1257*56bb7041Schristos 	  while ((1L << cg->bits) < cg->colors)
1258*56bb7041Schristos 	    ++cg->bits;
1259*56bb7041Schristos 	}
1260*56bb7041Schristos 
1261*56bb7041Schristos       cg->bytes = icondirs[i].bytes;
1262*56bb7041Schristos       cg->index = first_icon + i + 1;
1263*56bb7041Schristos 
1264*56bb7041Schristos       *pp = cg;
1265*56bb7041Schristos       pp = &(*pp)->next;
1266*56bb7041Schristos     }
1267*56bb7041Schristos 
1268*56bb7041Schristos   free (icondirs);
1269*56bb7041Schristos 
1270*56bb7041Schristos   r = define_standard_resource (&resources, RT_GROUP_ICON, id,
1271*56bb7041Schristos 				resinfo->language, 0);
1272*56bb7041Schristos   r->type = RES_TYPE_GROUP_ICON;
1273*56bb7041Schristos   r->u.group_icon = first;
1274*56bb7041Schristos   r->res_info = *resinfo;
1275*56bb7041Schristos }
1276*56bb7041Schristos 
1277*56bb7041Schristos static void
define_group_icon_rcdata(rc_res_id id,const rc_res_res_info * resinfo,rc_rcdata_item * data)1278*56bb7041Schristos define_group_icon_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
1279*56bb7041Schristos 			  rc_rcdata_item *data)
1280*56bb7041Schristos {
1281*56bb7041Schristos   rc_res_resource *r;
1282*56bb7041Schristos   rc_group_icon *cg, *first, *cur;
1283*56bb7041Schristos   rc_uint_type len_data;
1284*56bb7041Schristos   bfd_byte *pb_data;
1285*56bb7041Schristos 
1286*56bb7041Schristos   pb_data = rcdata_render_as_buffer (data, &len_data);
1287*56bb7041Schristos 
1288*56bb7041Schristos   cur = NULL;
1289*56bb7041Schristos   first = NULL;
1290*56bb7041Schristos 
1291*56bb7041Schristos   while (len_data >= 6)
1292*56bb7041Schristos     {
1293*56bb7041Schristos       int c, i;
1294*56bb7041Schristos       unsigned short type;
1295*56bb7041Schristos       type = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2);
1296*56bb7041Schristos       if (type != 1)
1297*56bb7041Schristos 	fatal (_("unexpected group icon type %d"), type);
1298*56bb7041Schristos       c = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4);
1299*56bb7041Schristos       len_data -= 6;
1300*56bb7041Schristos       pb_data += 6;
1301*56bb7041Schristos 
1302*56bb7041Schristos       for (i = 0; i < c; i++)
1303*56bb7041Schristos 	{
1304*56bb7041Schristos 	  if (len_data < 14)
1305*56bb7041Schristos 	    fatal ("too small group icon rcdata");
1306*56bb7041Schristos 	  cg = (rc_group_icon *) res_alloc (sizeof (rc_group_icon));
1307*56bb7041Schristos 	  cg->next = NULL;
1308*56bb7041Schristos 	  cg->width = pb_data[0];
1309*56bb7041Schristos 	  cg->height = pb_data[1];
1310*56bb7041Schristos 	  cg->colors = pb_data[2];
1311*56bb7041Schristos 	  cg->planes = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4);
1312*56bb7041Schristos 	  cg->bits =  windres_get_16 (&wrtarget, pb_data + 6, len_data - 6);
1313*56bb7041Schristos 	  cg->bytes = windres_get_32 (&wrtarget, pb_data + 8, len_data - 8);
1314*56bb7041Schristos 	  cg->index = windres_get_16 (&wrtarget, pb_data + 12, len_data - 12);
1315*56bb7041Schristos 	  if (! first)
1316*56bb7041Schristos 	    first = cg;
1317*56bb7041Schristos 	  else
1318*56bb7041Schristos 	    cur->next = cg;
1319*56bb7041Schristos 	  cur = cg;
1320*56bb7041Schristos 	  pb_data += 14;
1321*56bb7041Schristos 	  len_data -= 14;
1322*56bb7041Schristos 	}
1323*56bb7041Schristos     }
1324*56bb7041Schristos   r = define_standard_resource (&resources, RT_GROUP_ICON, id,
1325*56bb7041Schristos 				resinfo->language, 0);
1326*56bb7041Schristos   r->type = RES_TYPE_GROUP_ICON;
1327*56bb7041Schristos   r->u.group_icon = first;
1328*56bb7041Schristos   r->res_info = *resinfo;
1329*56bb7041Schristos }
1330*56bb7041Schristos 
1331*56bb7041Schristos static void
define_group_cursor_rcdata(rc_res_id id,const rc_res_res_info * resinfo,rc_rcdata_item * data)1332*56bb7041Schristos define_group_cursor_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
1333*56bb7041Schristos 			    rc_rcdata_item *data)
1334*56bb7041Schristos {
1335*56bb7041Schristos   rc_res_resource *r;
1336*56bb7041Schristos   rc_group_cursor *cg, *first, *cur;
1337*56bb7041Schristos   rc_uint_type len_data;
1338*56bb7041Schristos   bfd_byte *pb_data;
1339*56bb7041Schristos 
1340*56bb7041Schristos   pb_data = rcdata_render_as_buffer (data, &len_data);
1341*56bb7041Schristos 
1342*56bb7041Schristos   first = cur = NULL;
1343*56bb7041Schristos 
1344*56bb7041Schristos   while (len_data >= 6)
1345*56bb7041Schristos     {
1346*56bb7041Schristos       int c, i;
1347*56bb7041Schristos       unsigned short type;
1348*56bb7041Schristos       type = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2);
1349*56bb7041Schristos       if (type != 2)
1350*56bb7041Schristos 	fatal (_("unexpected group cursor type %d"), type);
1351*56bb7041Schristos       c = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4);
1352*56bb7041Schristos       len_data -= 6;
1353*56bb7041Schristos       pb_data += 6;
1354*56bb7041Schristos 
1355*56bb7041Schristos       for (i = 0; i < c; i++)
1356*56bb7041Schristos 	{
1357*56bb7041Schristos 	  if (len_data < 14)
1358*56bb7041Schristos 	    fatal ("too small group icon rcdata");
1359*56bb7041Schristos 	  cg = (rc_group_cursor *) res_alloc (sizeof (rc_group_cursor));
1360*56bb7041Schristos 	  cg->next = NULL;
1361*56bb7041Schristos 	  cg->width = windres_get_16 (&wrtarget, pb_data, len_data);
1362*56bb7041Schristos 	  cg->height = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2);
1363*56bb7041Schristos 	  cg->planes = windres_get_16 (&wrtarget, pb_data + 4, len_data - 4);
1364*56bb7041Schristos 	  cg->bits =  windres_get_16 (&wrtarget, pb_data + 6, len_data - 6);
1365*56bb7041Schristos 	  cg->bytes = windres_get_32 (&wrtarget, pb_data + 8, len_data - 8);
1366*56bb7041Schristos 	  cg->index = windres_get_16 (&wrtarget, pb_data + 12, len_data - 12);
1367*56bb7041Schristos 	  if (! first)
1368*56bb7041Schristos 	    first = cg;
1369*56bb7041Schristos 	  else
1370*56bb7041Schristos 	    cur->next = cg;
1371*56bb7041Schristos 	  cur = cg;
1372*56bb7041Schristos 	  pb_data += 14;
1373*56bb7041Schristos 	  len_data -= 14;
1374*56bb7041Schristos 	}
1375*56bb7041Schristos     }
1376*56bb7041Schristos 
1377*56bb7041Schristos   r = define_standard_resource (&resources, RT_GROUP_ICON, id,
1378*56bb7041Schristos 				resinfo->language, 0);
1379*56bb7041Schristos   r->type = RES_TYPE_GROUP_CURSOR;
1380*56bb7041Schristos   r->u.group_cursor = first;
1381*56bb7041Schristos   r->res_info = *resinfo;
1382*56bb7041Schristos }
1383*56bb7041Schristos 
1384*56bb7041Schristos static void
define_cursor_rcdata(rc_res_id id,const rc_res_res_info * resinfo,rc_rcdata_item * data)1385*56bb7041Schristos define_cursor_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
1386*56bb7041Schristos 		      rc_rcdata_item *data)
1387*56bb7041Schristos {
1388*56bb7041Schristos   rc_cursor *c;
1389*56bb7041Schristos   rc_res_resource *r;
1390*56bb7041Schristos   rc_uint_type len_data;
1391*56bb7041Schristos   bfd_byte *pb_data;
1392*56bb7041Schristos 
1393*56bb7041Schristos   pb_data = rcdata_render_as_buffer (data, &len_data);
1394*56bb7041Schristos 
1395*56bb7041Schristos   c = (rc_cursor *) res_alloc (sizeof (rc_cursor));
1396*56bb7041Schristos   c->xhotspot = windres_get_16 (&wrtarget, pb_data, len_data);
1397*56bb7041Schristos   c->yhotspot = windres_get_16 (&wrtarget, pb_data + 2, len_data - 2);
1398*56bb7041Schristos   c->length = len_data - BIN_CURSOR_SIZE;
1399*56bb7041Schristos   c->data = (const bfd_byte *) (data + BIN_CURSOR_SIZE);
1400*56bb7041Schristos 
1401*56bb7041Schristos   r = define_standard_resource (&resources, RT_CURSOR, id, resinfo->language, 0);
1402*56bb7041Schristos   r->type = RES_TYPE_CURSOR;
1403*56bb7041Schristos   r->u.cursor = c;
1404*56bb7041Schristos   r->res_info = *resinfo;
1405*56bb7041Schristos }
1406*56bb7041Schristos 
1407*56bb7041Schristos static void
define_bitmap_rcdata(rc_res_id id,const rc_res_res_info * resinfo,rc_rcdata_item * data)1408*56bb7041Schristos define_bitmap_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
1409*56bb7041Schristos 		      rc_rcdata_item *data)
1410*56bb7041Schristos {
1411*56bb7041Schristos   rc_res_resource *r;
1412*56bb7041Schristos   rc_uint_type len_data;
1413*56bb7041Schristos   bfd_byte *pb_data;
1414*56bb7041Schristos 
1415*56bb7041Schristos   pb_data = rcdata_render_as_buffer (data, &len_data);
1416*56bb7041Schristos 
1417*56bb7041Schristos   r = define_standard_resource (&resources, RT_BITMAP, id, resinfo->language, 0);
1418*56bb7041Schristos   r->type = RES_TYPE_BITMAP;
1419*56bb7041Schristos   r->u.data.length = len_data;
1420*56bb7041Schristos   r->u.data.data = pb_data;
1421*56bb7041Schristos   r->res_info = *resinfo;
1422*56bb7041Schristos }
1423*56bb7041Schristos 
1424*56bb7041Schristos static void
define_icon_rcdata(rc_res_id id,const rc_res_res_info * resinfo,rc_rcdata_item * data)1425*56bb7041Schristos define_icon_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
1426*56bb7041Schristos 		    rc_rcdata_item *data)
1427*56bb7041Schristos {
1428*56bb7041Schristos   rc_res_resource *r;
1429*56bb7041Schristos   rc_uint_type len_data;
1430*56bb7041Schristos   bfd_byte *pb_data;
1431*56bb7041Schristos 
1432*56bb7041Schristos   pb_data = rcdata_render_as_buffer (data, &len_data);
1433*56bb7041Schristos 
1434*56bb7041Schristos   r = define_standard_resource (&resources, RT_ICON, id, resinfo->language, 0);
1435*56bb7041Schristos   r->type = RES_TYPE_ICON;
1436*56bb7041Schristos   r->u.data.length = len_data;
1437*56bb7041Schristos   r->u.data.data = pb_data;
1438*56bb7041Schristos   r->res_info = *resinfo;
1439*56bb7041Schristos }
1440*56bb7041Schristos 
1441*56bb7041Schristos /* Define a menu resource.  */
1442*56bb7041Schristos 
1443*56bb7041Schristos void
define_menu(rc_res_id id,const rc_res_res_info * resinfo,rc_menuitem * menuitems)1444*56bb7041Schristos define_menu (rc_res_id id, const rc_res_res_info *resinfo,
1445*56bb7041Schristos 	     rc_menuitem *menuitems)
1446*56bb7041Schristos {
1447*56bb7041Schristos   rc_menu *m;
1448*56bb7041Schristos   rc_res_resource *r;
1449*56bb7041Schristos 
1450*56bb7041Schristos   m = (rc_menu *) res_alloc (sizeof (rc_menu));
1451*56bb7041Schristos   m->items = menuitems;
1452*56bb7041Schristos   m->help = 0;
1453*56bb7041Schristos 
1454*56bb7041Schristos   r = define_standard_resource (&resources, RT_MENU, id, resinfo->language, 0);
1455*56bb7041Schristos   r->type = RES_TYPE_MENU;
1456*56bb7041Schristos   r->u.menu = m;
1457*56bb7041Schristos   r->res_info = *resinfo;
1458*56bb7041Schristos }
1459*56bb7041Schristos 
1460*56bb7041Schristos /* Define a menu item.  This does not define a resource, but merely
1461*56bb7041Schristos    allocates and fills in a structure.  */
1462*56bb7041Schristos 
1463*56bb7041Schristos rc_menuitem *
define_menuitem(const unichar * text,rc_uint_type menuid,rc_uint_type type,rc_uint_type state,rc_uint_type help,rc_menuitem * menuitems)1464*56bb7041Schristos define_menuitem (const unichar *text, rc_uint_type menuid, rc_uint_type type,
1465*56bb7041Schristos 		 rc_uint_type state, rc_uint_type help,
1466*56bb7041Schristos 		 rc_menuitem *menuitems)
1467*56bb7041Schristos {
1468*56bb7041Schristos   rc_menuitem *mi;
1469*56bb7041Schristos 
1470*56bb7041Schristos   mi = (rc_menuitem *) res_alloc (sizeof (rc_menuitem));
1471*56bb7041Schristos   mi->next = NULL;
1472*56bb7041Schristos   mi->type = type;
1473*56bb7041Schristos   mi->state = state;
1474*56bb7041Schristos   mi->id = menuid;
1475*56bb7041Schristos   mi->text = unichar_dup (text);
1476*56bb7041Schristos   mi->help = help;
1477*56bb7041Schristos   mi->popup = menuitems;
1478*56bb7041Schristos   return mi;
1479*56bb7041Schristos }
1480*56bb7041Schristos 
1481*56bb7041Schristos /* Define a messagetable resource.  */
1482*56bb7041Schristos 
1483*56bb7041Schristos void
define_messagetable(rc_res_id id,const rc_res_res_info * resinfo,const char * filename)1484*56bb7041Schristos define_messagetable (rc_res_id id, const rc_res_res_info *resinfo,
1485*56bb7041Schristos 		     const char *filename)
1486*56bb7041Schristos {
1487*56bb7041Schristos   FILE *e;
1488*56bb7041Schristos   char *real_filename;
1489*56bb7041Schristos   struct stat s;
1490*56bb7041Schristos   bfd_byte *data;
1491*56bb7041Schristos   rc_res_resource *r;
1492*56bb7041Schristos 
1493*56bb7041Schristos   e = open_file_search (filename, FOPEN_RB, "messagetable file",
1494*56bb7041Schristos 			&real_filename);
1495*56bb7041Schristos 
1496*56bb7041Schristos   if (stat (real_filename, &s) < 0)
1497*56bb7041Schristos     fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
1498*56bb7041Schristos 	   strerror (errno));
1499*56bb7041Schristos 
1500*56bb7041Schristos   data = (bfd_byte *) res_alloc (s.st_size);
1501*56bb7041Schristos 
1502*56bb7041Schristos   get_data (e, data, s.st_size, real_filename);
1503*56bb7041Schristos 
1504*56bb7041Schristos   fclose (e);
1505*56bb7041Schristos   free (real_filename);
1506*56bb7041Schristos 
1507*56bb7041Schristos   r = define_standard_resource (&resources, RT_MESSAGETABLE, id,
1508*56bb7041Schristos 				resinfo->language, 0);
1509*56bb7041Schristos 
1510*56bb7041Schristos   r->type = RES_TYPE_MESSAGETABLE;
1511*56bb7041Schristos   r->u.data.length = s.st_size;
1512*56bb7041Schristos   r->u.data.data = data;
1513*56bb7041Schristos   r->res_info = *resinfo;
1514*56bb7041Schristos }
1515*56bb7041Schristos 
1516*56bb7041Schristos /* Define an rcdata resource.  */
1517*56bb7041Schristos 
1518*56bb7041Schristos void
define_rcdata(rc_res_id id,const rc_res_res_info * resinfo,rc_rcdata_item * data)1519*56bb7041Schristos define_rcdata (rc_res_id id, const rc_res_res_info *resinfo,
1520*56bb7041Schristos 	       rc_rcdata_item *data)
1521*56bb7041Schristos {
1522*56bb7041Schristos   rc_res_resource *r;
1523*56bb7041Schristos 
1524*56bb7041Schristos   r = define_standard_resource (&resources, RT_RCDATA, id,
1525*56bb7041Schristos 				resinfo->language, 0);
1526*56bb7041Schristos   r->type = RES_TYPE_RCDATA;
1527*56bb7041Schristos   r->u.rcdata = data;
1528*56bb7041Schristos   r->res_info = *resinfo;
1529*56bb7041Schristos }
1530*56bb7041Schristos 
1531*56bb7041Schristos /* Create an rcdata item holding a string.  */
1532*56bb7041Schristos 
1533*56bb7041Schristos rc_rcdata_item *
define_rcdata_string(const char * string,rc_uint_type len)1534*56bb7041Schristos define_rcdata_string (const char *string, rc_uint_type len)
1535*56bb7041Schristos {
1536*56bb7041Schristos   rc_rcdata_item *ri;
1537*56bb7041Schristos   char *s;
1538*56bb7041Schristos 
1539*56bb7041Schristos   ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
1540*56bb7041Schristos   ri->next = NULL;
1541*56bb7041Schristos   ri->type = RCDATA_STRING;
1542*56bb7041Schristos   ri->u.string.length = len;
1543*56bb7041Schristos   s = (char *) res_alloc (len);
1544*56bb7041Schristos   memcpy (s, string, len);
1545*56bb7041Schristos   ri->u.string.s = s;
1546*56bb7041Schristos 
1547*56bb7041Schristos   return ri;
1548*56bb7041Schristos }
1549*56bb7041Schristos 
1550*56bb7041Schristos /* Create an rcdata item holding a unicode string.  */
1551*56bb7041Schristos 
1552*56bb7041Schristos rc_rcdata_item *
define_rcdata_unistring(const unichar * string,rc_uint_type len)1553*56bb7041Schristos define_rcdata_unistring (const unichar *string, rc_uint_type len)
1554*56bb7041Schristos {
1555*56bb7041Schristos   rc_rcdata_item *ri;
1556*56bb7041Schristos   unichar *s;
1557*56bb7041Schristos 
1558*56bb7041Schristos   ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
1559*56bb7041Schristos   ri->next = NULL;
1560*56bb7041Schristos   ri->type = RCDATA_WSTRING;
1561*56bb7041Schristos   ri->u.wstring.length = len;
1562*56bb7041Schristos   s = (unichar *) res_alloc (len * sizeof (unichar));
1563*56bb7041Schristos   memcpy (s, string, len * sizeof (unichar));
1564*56bb7041Schristos   ri->u.wstring.w = s;
1565*56bb7041Schristos 
1566*56bb7041Schristos   return ri;
1567*56bb7041Schristos }
1568*56bb7041Schristos 
1569*56bb7041Schristos /* Create an rcdata item holding a number.  */
1570*56bb7041Schristos 
1571*56bb7041Schristos rc_rcdata_item *
define_rcdata_number(rc_uint_type val,int dword)1572*56bb7041Schristos define_rcdata_number (rc_uint_type val, int dword)
1573*56bb7041Schristos {
1574*56bb7041Schristos   rc_rcdata_item *ri;
1575*56bb7041Schristos 
1576*56bb7041Schristos   ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
1577*56bb7041Schristos   ri->next = NULL;
1578*56bb7041Schristos   ri->type = dword ? RCDATA_DWORD : RCDATA_WORD;
1579*56bb7041Schristos   ri->u.word = val;
1580*56bb7041Schristos 
1581*56bb7041Schristos   return ri;
1582*56bb7041Schristos }
1583*56bb7041Schristos 
1584*56bb7041Schristos /* Define a stringtable resource.  This is called for each string
1585*56bb7041Schristos    which appears in a STRINGTABLE statement.  */
1586*56bb7041Schristos 
1587*56bb7041Schristos void
define_stringtable(const rc_res_res_info * resinfo,rc_uint_type stringid,const unichar * string,int len)1588*56bb7041Schristos define_stringtable (const rc_res_res_info *resinfo,
1589*56bb7041Schristos 		    rc_uint_type stringid, const unichar *string, int len)
1590*56bb7041Schristos {
1591*56bb7041Schristos   unichar *h;
1592*56bb7041Schristos   rc_res_id id;
1593*56bb7041Schristos   rc_res_resource *r;
1594*56bb7041Schristos 
1595*56bb7041Schristos   id.named = 0;
1596*56bb7041Schristos   id.u.id = (stringid >> 4) + 1;
1597*56bb7041Schristos   r = define_standard_resource (&resources, RT_STRING, id,
1598*56bb7041Schristos 				resinfo->language, 1);
1599*56bb7041Schristos 
1600*56bb7041Schristos   if (r->type == RES_TYPE_UNINITIALIZED)
1601*56bb7041Schristos     {
1602*56bb7041Schristos       int i;
1603*56bb7041Schristos 
1604*56bb7041Schristos       r->type = RES_TYPE_STRINGTABLE;
1605*56bb7041Schristos       r->u.stringtable = ((rc_stringtable *)
1606*56bb7041Schristos 			  res_alloc (sizeof (rc_stringtable)));
1607*56bb7041Schristos       for (i = 0; i < 16; i++)
1608*56bb7041Schristos 	{
1609*56bb7041Schristos 	  r->u.stringtable->strings[i].length = 0;
1610*56bb7041Schristos 	  r->u.stringtable->strings[i].string = NULL;
1611*56bb7041Schristos 	}
1612*56bb7041Schristos 
1613*56bb7041Schristos       r->res_info = *resinfo;
1614*56bb7041Schristos     }
1615*56bb7041Schristos   h = (unichar *) res_alloc ((len + 1) * sizeof (unichar));
1616*56bb7041Schristos   if (len)
1617*56bb7041Schristos     memcpy (h, string, len * sizeof (unichar));
1618*56bb7041Schristos   h[len] = 0;
1619*56bb7041Schristos   r->u.stringtable->strings[stringid & 0xf].length = (rc_uint_type) len;
1620*56bb7041Schristos   r->u.stringtable->strings[stringid & 0xf].string = h;
1621*56bb7041Schristos }
1622*56bb7041Schristos 
1623*56bb7041Schristos void
define_toolbar(rc_res_id id,rc_res_res_info * resinfo,rc_uint_type width,rc_uint_type height,rc_toolbar_item * items)1624*56bb7041Schristos define_toolbar (rc_res_id id, rc_res_res_info *resinfo, rc_uint_type width, rc_uint_type height,
1625*56bb7041Schristos 		rc_toolbar_item *items)
1626*56bb7041Schristos {
1627*56bb7041Schristos   rc_toolbar *t;
1628*56bb7041Schristos   rc_res_resource *r;
1629*56bb7041Schristos 
1630*56bb7041Schristos   t = (rc_toolbar *) res_alloc (sizeof (rc_toolbar));
1631*56bb7041Schristos   t->button_width = width;
1632*56bb7041Schristos   t->button_height = height;
1633*56bb7041Schristos   t->nitems = 0;
1634*56bb7041Schristos   t->items = items;
1635*56bb7041Schristos   while (items != NULL)
1636*56bb7041Schristos   {
1637*56bb7041Schristos     t->nitems+=1;
1638*56bb7041Schristos     items = items->next;
1639*56bb7041Schristos   }
1640*56bb7041Schristos   r = define_standard_resource (&resources, RT_TOOLBAR, id, resinfo->language, 0);
1641*56bb7041Schristos   r->type = RES_TYPE_TOOLBAR;
1642*56bb7041Schristos   r->u.toolbar = t;
1643*56bb7041Schristos   r->res_info = *resinfo;
1644*56bb7041Schristos }
1645*56bb7041Schristos 
1646*56bb7041Schristos /* Define a user data resource where the data is in the rc file.  */
1647*56bb7041Schristos 
1648*56bb7041Schristos void
define_user_data(rc_res_id id,rc_res_id type,const rc_res_res_info * resinfo,rc_rcdata_item * data)1649*56bb7041Schristos define_user_data (rc_res_id id, rc_res_id type,
1650*56bb7041Schristos 		  const rc_res_res_info *resinfo,
1651*56bb7041Schristos 		  rc_rcdata_item *data)
1652*56bb7041Schristos {
1653*56bb7041Schristos   rc_res_id ids[3];
1654*56bb7041Schristos   rc_res_resource *r;
1655*56bb7041Schristos   bfd_byte *pb_data;
1656*56bb7041Schristos   rc_uint_type len_data;
1657*56bb7041Schristos 
1658*56bb7041Schristos   /* We have to check if the binary data is parsed specially.  */
1659*56bb7041Schristos   if (type.named == 0)
1660*56bb7041Schristos     {
1661*56bb7041Schristos       switch (type.u.id)
1662*56bb7041Schristos       {
1663*56bb7041Schristos       case RT_FONTDIR:
1664*56bb7041Schristos 	define_fontdir_rcdata (id, resinfo, data);
1665*56bb7041Schristos 	return;
1666*56bb7041Schristos       case RT_FONT:
1667*56bb7041Schristos 	define_font_rcdata (id, resinfo, data);
1668*56bb7041Schristos 	return;
1669*56bb7041Schristos       case RT_ICON:
1670*56bb7041Schristos 	define_icon_rcdata (id, resinfo, data);
1671*56bb7041Schristos 	return;
1672*56bb7041Schristos       case RT_BITMAP:
1673*56bb7041Schristos 	define_bitmap_rcdata (id, resinfo, data);
1674*56bb7041Schristos 	return;
1675*56bb7041Schristos       case RT_CURSOR:
1676*56bb7041Schristos 	define_cursor_rcdata (id, resinfo, data);
1677*56bb7041Schristos 	return;
1678*56bb7041Schristos       case RT_GROUP_ICON:
1679*56bb7041Schristos 	define_group_icon_rcdata (id, resinfo, data);
1680*56bb7041Schristos 	return;
1681*56bb7041Schristos       case RT_GROUP_CURSOR:
1682*56bb7041Schristos 	define_group_cursor_rcdata (id, resinfo, data);
1683*56bb7041Schristos 	return;
1684*56bb7041Schristos       case RT_MESSAGETABLE:
1685*56bb7041Schristos 	define_messagetable_rcdata (id, resinfo, data);
1686*56bb7041Schristos 	return;
1687*56bb7041Schristos       default:
1688*56bb7041Schristos 	/* Treat as normal user-data.  */
1689*56bb7041Schristos 	break;
1690*56bb7041Schristos       }
1691*56bb7041Schristos     }
1692*56bb7041Schristos   ids[0] = type;
1693*56bb7041Schristos   ids[1] = id;
1694*56bb7041Schristos   ids[2].named = 0;
1695*56bb7041Schristos   ids[2].u.id = resinfo->language;
1696*56bb7041Schristos 
1697*56bb7041Schristos   r = define_resource (& resources, 3, ids, 0);
1698*56bb7041Schristos   r->type = RES_TYPE_USERDATA;
1699*56bb7041Schristos   r->u.userdata = ((rc_rcdata_item *)
1700*56bb7041Schristos 		   res_alloc (sizeof (rc_rcdata_item)));
1701*56bb7041Schristos   r->u.userdata->next = NULL;
1702*56bb7041Schristos   r->u.userdata->type = RCDATA_BUFFER;
1703*56bb7041Schristos   pb_data = rcdata_render_as_buffer (data, &len_data);
1704*56bb7041Schristos   r->u.userdata->u.buffer.length = len_data;
1705*56bb7041Schristos   r->u.userdata->u.buffer.data = pb_data;
1706*56bb7041Schristos   r->res_info = *resinfo;
1707*56bb7041Schristos }
1708*56bb7041Schristos 
1709*56bb7041Schristos void
define_rcdata_file(rc_res_id id,const rc_res_res_info * resinfo,const char * filename)1710*56bb7041Schristos define_rcdata_file (rc_res_id id, const rc_res_res_info *resinfo,
1711*56bb7041Schristos 		    const char *filename)
1712*56bb7041Schristos {
1713*56bb7041Schristos   rc_rcdata_item *ri;
1714*56bb7041Schristos   FILE *e;
1715*56bb7041Schristos   char *real_filename;
1716*56bb7041Schristos   struct stat s;
1717*56bb7041Schristos   bfd_byte *data;
1718*56bb7041Schristos 
1719*56bb7041Schristos   e = open_file_search (filename, FOPEN_RB, "file", &real_filename);
1720*56bb7041Schristos 
1721*56bb7041Schristos 
1722*56bb7041Schristos   if (stat (real_filename, &s) < 0)
1723*56bb7041Schristos     fatal (_("stat failed on file `%s': %s"), real_filename,
1724*56bb7041Schristos 	   strerror (errno));
1725*56bb7041Schristos 
1726*56bb7041Schristos   data = (bfd_byte *) res_alloc (s.st_size);
1727*56bb7041Schristos 
1728*56bb7041Schristos   get_data (e, data, s.st_size, real_filename);
1729*56bb7041Schristos 
1730*56bb7041Schristos   fclose (e);
1731*56bb7041Schristos   free (real_filename);
1732*56bb7041Schristos 
1733*56bb7041Schristos   ri = (rc_rcdata_item *) res_alloc (sizeof (rc_rcdata_item));
1734*56bb7041Schristos   ri->next = NULL;
1735*56bb7041Schristos   ri->type = RCDATA_BUFFER;
1736*56bb7041Schristos   ri->u.buffer.length = s.st_size;
1737*56bb7041Schristos   ri->u.buffer.data = data;
1738*56bb7041Schristos 
1739*56bb7041Schristos   define_rcdata (id, resinfo, ri);
1740*56bb7041Schristos }
1741*56bb7041Schristos 
1742*56bb7041Schristos /* Define a user data resource where the data is in a file.  */
1743*56bb7041Schristos 
1744*56bb7041Schristos void
define_user_file(rc_res_id id,rc_res_id type,const rc_res_res_info * resinfo,const char * filename)1745*56bb7041Schristos define_user_file (rc_res_id id, rc_res_id type,
1746*56bb7041Schristos 		  const rc_res_res_info *resinfo, const char *filename)
1747*56bb7041Schristos {
1748*56bb7041Schristos   FILE *e;
1749*56bb7041Schristos   char *real_filename;
1750*56bb7041Schristos   struct stat s;
1751*56bb7041Schristos   bfd_byte *data;
1752*56bb7041Schristos   rc_res_id ids[3];
1753*56bb7041Schristos   rc_res_resource *r;
1754*56bb7041Schristos 
1755*56bb7041Schristos   e = open_file_search (filename, FOPEN_RB, "file", &real_filename);
1756*56bb7041Schristos 
1757*56bb7041Schristos   if (stat (real_filename, &s) < 0)
1758*56bb7041Schristos     fatal (_("stat failed on file `%s': %s"), real_filename,
1759*56bb7041Schristos 	   strerror (errno));
1760*56bb7041Schristos 
1761*56bb7041Schristos   data = (bfd_byte *) res_alloc (s.st_size);
1762*56bb7041Schristos 
1763*56bb7041Schristos   get_data (e, data, s.st_size, real_filename);
1764*56bb7041Schristos 
1765*56bb7041Schristos   fclose (e);
1766*56bb7041Schristos   free (real_filename);
1767*56bb7041Schristos 
1768*56bb7041Schristos   ids[0] = type;
1769*56bb7041Schristos   ids[1] = id;
1770*56bb7041Schristos   ids[2].named = 0;
1771*56bb7041Schristos   ids[2].u.id = resinfo->language;
1772*56bb7041Schristos 
1773*56bb7041Schristos   r = define_resource (&resources, 3, ids, 0);
1774*56bb7041Schristos   r->type = RES_TYPE_USERDATA;
1775*56bb7041Schristos   r->u.userdata = ((rc_rcdata_item *)
1776*56bb7041Schristos 		   res_alloc (sizeof (rc_rcdata_item)));
1777*56bb7041Schristos   r->u.userdata->next = NULL;
1778*56bb7041Schristos   r->u.userdata->type = RCDATA_BUFFER;
1779*56bb7041Schristos   r->u.userdata->u.buffer.length = s.st_size;
1780*56bb7041Schristos   r->u.userdata->u.buffer.data = data;
1781*56bb7041Schristos   r->res_info = *resinfo;
1782*56bb7041Schristos }
1783*56bb7041Schristos 
1784*56bb7041Schristos /* Define a versioninfo resource.  */
1785*56bb7041Schristos 
1786*56bb7041Schristos void
define_versioninfo(rc_res_id id,rc_uint_type language,rc_fixed_versioninfo * fixedverinfo,rc_ver_info * verinfo)1787*56bb7041Schristos define_versioninfo (rc_res_id id, rc_uint_type language,
1788*56bb7041Schristos 		    rc_fixed_versioninfo *fixedverinfo,
1789*56bb7041Schristos 		    rc_ver_info *verinfo)
1790*56bb7041Schristos {
1791*56bb7041Schristos   rc_res_resource *r;
1792*56bb7041Schristos 
1793*56bb7041Schristos   r = define_standard_resource (&resources, RT_VERSION, id, language, 0);
1794*56bb7041Schristos   r->type = RES_TYPE_VERSIONINFO;
1795*56bb7041Schristos   r->u.versioninfo = ((rc_versioninfo *)
1796*56bb7041Schristos 		      res_alloc (sizeof (rc_versioninfo)));
1797*56bb7041Schristos   r->u.versioninfo->fixed = fixedverinfo;
1798*56bb7041Schristos   r->u.versioninfo->var = verinfo;
1799*56bb7041Schristos   r->res_info.language = language;
1800*56bb7041Schristos }
1801*56bb7041Schristos 
1802*56bb7041Schristos /* Add string version info to a list of version information.  */
1803*56bb7041Schristos 
1804*56bb7041Schristos rc_ver_info *
append_ver_stringfileinfo(rc_ver_info * verinfo,rc_ver_stringtable * stringtables)1805*56bb7041Schristos append_ver_stringfileinfo (rc_ver_info *verinfo,
1806*56bb7041Schristos 			   rc_ver_stringtable *stringtables)
1807*56bb7041Schristos {
1808*56bb7041Schristos   rc_ver_info *vi, **pp;
1809*56bb7041Schristos 
1810*56bb7041Schristos   vi = (rc_ver_info *) res_alloc (sizeof (rc_ver_info));
1811*56bb7041Schristos   vi->next = NULL;
1812*56bb7041Schristos   vi->type = VERINFO_STRING;
1813*56bb7041Schristos   vi->u.string.stringtables = stringtables;
1814*56bb7041Schristos 
1815*56bb7041Schristos   for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1816*56bb7041Schristos     ;
1817*56bb7041Schristos   *pp = vi;
1818*56bb7041Schristos 
1819*56bb7041Schristos   return verinfo;
1820*56bb7041Schristos }
1821*56bb7041Schristos 
1822*56bb7041Schristos rc_ver_stringtable *
append_ver_stringtable(rc_ver_stringtable * stringtable,const char * language,rc_ver_stringinfo * strings)1823*56bb7041Schristos append_ver_stringtable (rc_ver_stringtable *stringtable,
1824*56bb7041Schristos 			const char *language,
1825*56bb7041Schristos 			rc_ver_stringinfo *strings)
1826*56bb7041Schristos {
1827*56bb7041Schristos   rc_ver_stringtable *vst, **pp;
1828*56bb7041Schristos 
1829*56bb7041Schristos   vst = (rc_ver_stringtable *) res_alloc (sizeof (rc_ver_stringtable));
1830*56bb7041Schristos   vst->next = NULL;
1831*56bb7041Schristos   unicode_from_ascii ((rc_uint_type *) NULL, &vst->language, language);
1832*56bb7041Schristos   vst->strings = strings;
1833*56bb7041Schristos 
1834*56bb7041Schristos   for (pp = &stringtable; *pp != NULL; pp = &(*pp)->next)
1835*56bb7041Schristos     ;
1836*56bb7041Schristos   *pp = vst;
1837*56bb7041Schristos 
1838*56bb7041Schristos   return stringtable;
1839*56bb7041Schristos }
1840*56bb7041Schristos 
1841*56bb7041Schristos /* Add variable version info to a list of version information.  */
1842*56bb7041Schristos 
1843*56bb7041Schristos rc_ver_info *
append_ver_varfileinfo(rc_ver_info * verinfo,const unichar * key,rc_ver_varinfo * var)1844*56bb7041Schristos append_ver_varfileinfo (rc_ver_info *verinfo, const unichar *key,
1845*56bb7041Schristos 			rc_ver_varinfo *var)
1846*56bb7041Schristos {
1847*56bb7041Schristos   rc_ver_info *vi, **pp;
1848*56bb7041Schristos 
1849*56bb7041Schristos   vi = (rc_ver_info *) res_alloc (sizeof *vi);
1850*56bb7041Schristos   vi->next = NULL;
1851*56bb7041Schristos   vi->type = VERINFO_VAR;
1852*56bb7041Schristos   vi->u.var.key = unichar_dup (key);
1853*56bb7041Schristos   vi->u.var.var = var;
1854*56bb7041Schristos 
1855*56bb7041Schristos   for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
1856*56bb7041Schristos     ;
1857*56bb7041Schristos   *pp = vi;
1858*56bb7041Schristos 
1859*56bb7041Schristos   return verinfo;
1860*56bb7041Schristos }
1861*56bb7041Schristos 
1862*56bb7041Schristos /* Append version string information to a list.  */
1863*56bb7041Schristos 
1864*56bb7041Schristos rc_ver_stringinfo *
append_verval(rc_ver_stringinfo * strings,const unichar * key,const unichar * value)1865*56bb7041Schristos append_verval (rc_ver_stringinfo *strings, const unichar *key,
1866*56bb7041Schristos 	       const unichar *value)
1867*56bb7041Schristos {
1868*56bb7041Schristos   rc_ver_stringinfo *vs, **pp;
1869*56bb7041Schristos 
1870*56bb7041Schristos   vs = (rc_ver_stringinfo *) res_alloc (sizeof (rc_ver_stringinfo));
1871*56bb7041Schristos   vs->next = NULL;
1872*56bb7041Schristos   vs->key = unichar_dup (key);
1873*56bb7041Schristos   vs->value = unichar_dup (value);
1874*56bb7041Schristos 
1875*56bb7041Schristos   for (pp = &strings; *pp != NULL; pp = &(*pp)->next)
1876*56bb7041Schristos     ;
1877*56bb7041Schristos   *pp = vs;
1878*56bb7041Schristos 
1879*56bb7041Schristos   return strings;
1880*56bb7041Schristos }
1881*56bb7041Schristos 
1882*56bb7041Schristos /* Append version variable information to a list.  */
1883*56bb7041Schristos 
1884*56bb7041Schristos rc_ver_varinfo *
append_vertrans(rc_ver_varinfo * var,rc_uint_type language,rc_uint_type charset)1885*56bb7041Schristos append_vertrans (rc_ver_varinfo *var, rc_uint_type language,
1886*56bb7041Schristos 		 rc_uint_type charset)
1887*56bb7041Schristos {
1888*56bb7041Schristos   rc_ver_varinfo *vv, **pp;
1889*56bb7041Schristos 
1890*56bb7041Schristos   vv = (rc_ver_varinfo *) res_alloc (sizeof (rc_ver_varinfo));
1891*56bb7041Schristos   vv->next = NULL;
1892*56bb7041Schristos   vv->language = language;
1893*56bb7041Schristos   vv->charset = charset;
1894*56bb7041Schristos 
1895*56bb7041Schristos   for (pp = &var; *pp != NULL; pp = &(*pp)->next)
1896*56bb7041Schristos     ;
1897*56bb7041Schristos   *pp = vv;
1898*56bb7041Schristos 
1899*56bb7041Schristos   return var;
1900*56bb7041Schristos }
1901*56bb7041Schristos 
1902*56bb7041Schristos /* Local functions used to write out an rc file.  */
1903*56bb7041Schristos 
1904*56bb7041Schristos static void indent (FILE *, int);
1905*56bb7041Schristos static void write_rc_directory (FILE *, const rc_res_directory *, const rc_res_id *,
1906*56bb7041Schristos 				const rc_res_id *, rc_uint_type *, int);
1907*56bb7041Schristos static void write_rc_subdir (FILE *, const rc_res_entry *, const rc_res_id *,
1908*56bb7041Schristos 			     const rc_res_id *, rc_uint_type *, int);
1909*56bb7041Schristos static void write_rc_resource (FILE *, const rc_res_id *, const rc_res_id *,
1910*56bb7041Schristos 			       const rc_res_resource *, rc_uint_type *);
1911*56bb7041Schristos static void write_rc_accelerators (FILE *, const rc_accelerator *);
1912*56bb7041Schristos static void write_rc_cursor (FILE *, const rc_cursor *);
1913*56bb7041Schristos static void write_rc_group_cursor (FILE *, const rc_group_cursor *);
1914*56bb7041Schristos static void write_rc_dialog (FILE *, const rc_dialog *);
1915*56bb7041Schristos static void write_rc_dialog_control (FILE *, const rc_dialog_control *);
1916*56bb7041Schristos static void write_rc_fontdir (FILE *, const rc_fontdir *);
1917*56bb7041Schristos static void write_rc_group_icon (FILE *, const rc_group_icon *);
1918*56bb7041Schristos static void write_rc_menu (FILE *, const rc_menu *, int);
1919*56bb7041Schristos static void write_rc_toolbar (FILE *, const rc_toolbar *);
1920*56bb7041Schristos static void write_rc_menuitems (FILE *, const rc_menuitem *, int, int);
1921*56bb7041Schristos static void write_rc_messagetable (FILE *, rc_uint_type , const bfd_byte *);
1922*56bb7041Schristos 
1923*56bb7041Schristos static void write_rc_datablock (FILE *, rc_uint_type , const bfd_byte *, int, int, int);
1924*56bb7041Schristos static void write_rc_rcdata (FILE *, const rc_rcdata_item *, int);
1925*56bb7041Schristos static void write_rc_stringtable (FILE *, const rc_res_id *, const rc_stringtable *);
1926*56bb7041Schristos static void write_rc_versioninfo (FILE *, const rc_versioninfo *);
1927*56bb7041Schristos 
1928*56bb7041Schristos /* Indent a given number of spaces.  */
1929*56bb7041Schristos 
1930*56bb7041Schristos static void
indent(FILE * e,int c)1931*56bb7041Schristos indent (FILE *e, int c)
1932*56bb7041Schristos {
1933*56bb7041Schristos   int i;
1934*56bb7041Schristos 
1935*56bb7041Schristos   for (i = 0; i < c; i++)
1936*56bb7041Schristos     putc (' ', e);
1937*56bb7041Schristos }
1938*56bb7041Schristos 
1939*56bb7041Schristos /* Dump the resources we have read in the format of an rc file.
1940*56bb7041Schristos 
1941*56bb7041Schristos    Reasoned by the fact, that some resources need to be stored into file and
1942*56bb7041Schristos    refer to that file, we use the user-data model for that to express it binary
1943*56bb7041Schristos    without the need to store it somewhere externally.  */
1944*56bb7041Schristos 
1945*56bb7041Schristos void
write_rc_file(const char * filename,const rc_res_directory * res_dir)1946*56bb7041Schristos write_rc_file (const char *filename, const rc_res_directory *res_dir)
1947*56bb7041Schristos {
1948*56bb7041Schristos   FILE *e;
1949*56bb7041Schristos   rc_uint_type language;
1950*56bb7041Schristos 
1951*56bb7041Schristos   if (filename == NULL)
1952*56bb7041Schristos     e = stdout;
1953*56bb7041Schristos   else
1954*56bb7041Schristos     {
1955*56bb7041Schristos       e = fopen (filename, FOPEN_WT);
1956*56bb7041Schristos       if (e == NULL)
1957*56bb7041Schristos 	fatal (_("can't open `%s' for output: %s"), filename, strerror (errno));
1958*56bb7041Schristos     }
1959*56bb7041Schristos 
1960*56bb7041Schristos   language = (rc_uint_type) ((bfd_signed_vma) -1);
1961*56bb7041Schristos   write_rc_directory (e, res_dir, (const rc_res_id *) NULL,
1962*56bb7041Schristos 		      (const rc_res_id *) NULL, &language, 1);
1963*56bb7041Schristos }
1964*56bb7041Schristos 
1965*56bb7041Schristos /* Write out a directory.  E is the file to write to.  RD is the
1966*56bb7041Schristos    directory.  TYPE is a pointer to the level 1 ID which serves as the
1967*56bb7041Schristos    resource type.  NAME is a pointer to the level 2 ID which serves as
1968*56bb7041Schristos    an individual resource name.  LANGUAGE is a pointer to the current
1969*56bb7041Schristos    language.  LEVEL is the level in the tree.  */
1970*56bb7041Schristos 
1971*56bb7041Schristos static void
write_rc_directory(FILE * e,const rc_res_directory * rd,const rc_res_id * type,const rc_res_id * name,rc_uint_type * language,int level)1972*56bb7041Schristos write_rc_directory (FILE *e, const rc_res_directory *rd,
1973*56bb7041Schristos 		    const rc_res_id *type, const rc_res_id *name,
1974*56bb7041Schristos 		    rc_uint_type *language, int level)
1975*56bb7041Schristos {
1976*56bb7041Schristos   const rc_res_entry *re;
1977*56bb7041Schristos 
1978*56bb7041Schristos   /* Print out some COFF information that rc files can't represent.  */
1979*56bb7041Schristos   if (rd->time != 0 || rd->characteristics != 0 || rd->major != 0 || rd->minor != 0)
1980*56bb7041Schristos     {
1981*56bb7041Schristos       wr_printcomment (e, "COFF information not part of RC");
1982*56bb7041Schristos   if (rd->time != 0)
1983*56bb7041Schristos 	wr_printcomment (e, "Time stamp: %u", rd->time);
1984*56bb7041Schristos   if (rd->characteristics != 0)
1985*56bb7041Schristos 	wr_printcomment (e, "Characteristics: %u", rd->characteristics);
1986*56bb7041Schristos   if (rd->major != 0 || rd->minor != 0)
1987*56bb7041Schristos 	wr_printcomment (e, "Version major:%d minor:%d", rd->major, rd->minor);
1988*56bb7041Schristos     }
1989*56bb7041Schristos 
1990*56bb7041Schristos   for (re = rd->entries;  re != NULL; re = re->next)
1991*56bb7041Schristos     {
1992*56bb7041Schristos       switch (level)
1993*56bb7041Schristos 	{
1994*56bb7041Schristos 	case 1:
1995*56bb7041Schristos 	  /* If we're at level 1, the key of this resource is the
1996*56bb7041Schristos              type.  This normally duplicates the information we have
1997*56bb7041Schristos              stored with the resource itself, but we need to remember
1998*56bb7041Schristos              the type if this is a user define resource type.  */
1999*56bb7041Schristos 	  type = &re->id;
2000*56bb7041Schristos 	  break;
2001*56bb7041Schristos 
2002*56bb7041Schristos 	case 2:
2003*56bb7041Schristos 	  /* If we're at level 2, the key of this resource is the name
2004*56bb7041Schristos 	     we are going to use in the rc printout.  */
2005*56bb7041Schristos 	  name = &re->id;
2006*56bb7041Schristos 	  break;
2007*56bb7041Schristos 
2008*56bb7041Schristos 	case 3:
2009*56bb7041Schristos 	  /* If we're at level 3, then this key represents a language.
2010*56bb7041Schristos 	     Use it to update the current language.  */
2011*56bb7041Schristos 	  if (! re->id.named
2012*56bb7041Schristos 	      && re->id.u.id != (unsigned long) (unsigned int) *language
2013*56bb7041Schristos 	      && (re->id.u.id & 0xffff) == re->id.u.id)
2014*56bb7041Schristos 	    {
2015*56bb7041Schristos 	      wr_print (e, "LANGUAGE %u, %u\n",
2016*56bb7041Schristos 		       re->id.u.id & ((1 << SUBLANG_SHIFT) - 1),
2017*56bb7041Schristos 		       (re->id.u.id >> SUBLANG_SHIFT) & 0xff);
2018*56bb7041Schristos 	      *language = re->id.u.id;
2019*56bb7041Schristos 	    }
2020*56bb7041Schristos 	  break;
2021*56bb7041Schristos 
2022*56bb7041Schristos 	default:
2023*56bb7041Schristos 	  break;
2024*56bb7041Schristos 	}
2025*56bb7041Schristos 
2026*56bb7041Schristos       if (re->subdir)
2027*56bb7041Schristos 	write_rc_subdir (e, re, type, name, language, level);
2028*56bb7041Schristos       else
2029*56bb7041Schristos 	{
2030*56bb7041Schristos 	  if (level == 3)
2031*56bb7041Schristos 	    {
2032*56bb7041Schristos 	      /* This is the normal case: the three levels are
2033*56bb7041Schristos                  TYPE/NAME/LANGUAGE.  NAME will have been set at level
2034*56bb7041Schristos                  2, and represents the name to use.  We probably just
2035*56bb7041Schristos                  set LANGUAGE, and it will probably match what the
2036*56bb7041Schristos                  resource itself records if anything.  */
2037*56bb7041Schristos 	      write_rc_resource (e, type, name, re->u.res, language);
2038*56bb7041Schristos 	    }
2039*56bb7041Schristos 	  else
2040*56bb7041Schristos 	    {
2041*56bb7041Schristos 	      wr_printcomment (e, "Resource at unexpected level %d", level);
2042*56bb7041Schristos 	      write_rc_resource (e, type, (rc_res_id *) NULL, re->u.res,
2043*56bb7041Schristos 				 language);
2044*56bb7041Schristos 	    }
2045*56bb7041Schristos 	}
2046*56bb7041Schristos     }
2047*56bb7041Schristos   if (rd->entries == NULL)
2048*56bb7041Schristos     {
2049*56bb7041Schristos       wr_print_flush (e);
2050*56bb7041Schristos     }
2051*56bb7041Schristos }
2052*56bb7041Schristos 
2053*56bb7041Schristos /* Write out a subdirectory entry.  E is the file to write to.  RE is
2054*56bb7041Schristos    the subdirectory entry.  TYPE and NAME are pointers to higher level
2055*56bb7041Schristos    IDs, or NULL.  LANGUAGE is a pointer to the current language.
2056*56bb7041Schristos    LEVEL is the level in the tree.  */
2057*56bb7041Schristos 
2058*56bb7041Schristos static void
write_rc_subdir(FILE * e,const rc_res_entry * re,const rc_res_id * type,const rc_res_id * name,rc_uint_type * language,int level)2059*56bb7041Schristos write_rc_subdir (FILE *e, const rc_res_entry *re,
2060*56bb7041Schristos 		 const rc_res_id *type, const rc_res_id *name,
2061*56bb7041Schristos 		 rc_uint_type *language, int level)
2062*56bb7041Schristos {
2063*56bb7041Schristos   fprintf (e, "\n");
2064*56bb7041Schristos   switch (level)
2065*56bb7041Schristos     {
2066*56bb7041Schristos     case 1:
2067*56bb7041Schristos       wr_printcomment (e, "Type: ");
2068*56bb7041Schristos       if (re->id.named)
2069*56bb7041Schristos 	res_id_print (e, re->id, 1);
2070*56bb7041Schristos       else
2071*56bb7041Schristos 	{
2072*56bb7041Schristos 	  const char *s;
2073*56bb7041Schristos 
2074*56bb7041Schristos 	  switch (re->id.u.id)
2075*56bb7041Schristos 	    {
2076*56bb7041Schristos 	    case RT_CURSOR: s = "cursor"; break;
2077*56bb7041Schristos 	    case RT_BITMAP: s = "bitmap"; break;
2078*56bb7041Schristos 	    case RT_ICON: s = "icon"; break;
2079*56bb7041Schristos 	    case RT_MENU: s = "menu"; break;
2080*56bb7041Schristos 	    case RT_DIALOG: s = "dialog"; break;
2081*56bb7041Schristos 	    case RT_STRING: s = "stringtable"; break;
2082*56bb7041Schristos 	    case RT_FONTDIR: s = "fontdir"; break;
2083*56bb7041Schristos 	    case RT_FONT: s = "font"; break;
2084*56bb7041Schristos 	    case RT_ACCELERATOR: s = "accelerators"; break;
2085*56bb7041Schristos 	    case RT_RCDATA: s = "rcdata"; break;
2086*56bb7041Schristos 	    case RT_MESSAGETABLE: s = "messagetable"; break;
2087*56bb7041Schristos 	    case RT_GROUP_CURSOR: s = "group cursor"; break;
2088*56bb7041Schristos 	    case RT_GROUP_ICON: s = "group icon"; break;
2089*56bb7041Schristos 	    case RT_VERSION: s = "version"; break;
2090*56bb7041Schristos 	    case RT_DLGINCLUDE: s = "dlginclude"; break;
2091*56bb7041Schristos 	    case RT_PLUGPLAY: s = "plugplay"; break;
2092*56bb7041Schristos 	    case RT_VXD: s = "vxd"; break;
2093*56bb7041Schristos 	    case RT_ANICURSOR: s = "anicursor"; break;
2094*56bb7041Schristos 	    case RT_ANIICON: s = "aniicon"; break;
2095*56bb7041Schristos 	    case RT_TOOLBAR: s = "toolbar"; break;
2096*56bb7041Schristos 	    case RT_HTML: s = "html"; break;
2097*56bb7041Schristos 	    default: s = NULL; break;
2098*56bb7041Schristos 	    }
2099*56bb7041Schristos 
2100*56bb7041Schristos 	  if (s != NULL)
2101*56bb7041Schristos 	    fprintf (e, "%s", s);
2102*56bb7041Schristos 	  else
2103*56bb7041Schristos 	    res_id_print (e, re->id, 1);
2104*56bb7041Schristos 	}
2105*56bb7041Schristos       break;
2106*56bb7041Schristos 
2107*56bb7041Schristos     case 2:
2108*56bb7041Schristos       wr_printcomment (e, "Name: ");
2109*56bb7041Schristos       res_id_print (e, re->id, 1);
2110*56bb7041Schristos       break;
2111*56bb7041Schristos 
2112*56bb7041Schristos     case 3:
2113*56bb7041Schristos       wr_printcomment (e, "Language: ");
2114*56bb7041Schristos       res_id_print (e, re->id, 1);
2115*56bb7041Schristos       break;
2116*56bb7041Schristos 
2117*56bb7041Schristos     default:
2118*56bb7041Schristos       wr_printcomment (e, "Level %d: ", level);
2119*56bb7041Schristos       res_id_print (e, re->id, 1);
2120*56bb7041Schristos     }
2121*56bb7041Schristos 
2122*56bb7041Schristos   write_rc_directory (e, re->u.dir, type, name, language, level + 1);
2123*56bb7041Schristos }
2124*56bb7041Schristos 
2125*56bb7041Schristos /* Write out a single resource.  E is the file to write to.  TYPE is a
2126*56bb7041Schristos    pointer to the type of the resource.  NAME is a pointer to the name
2127*56bb7041Schristos    of the resource; it will be NULL if there is a level mismatch.  RES
2128*56bb7041Schristos    is the resource data.  LANGUAGE is a pointer to the current
2129*56bb7041Schristos    language.  */
2130*56bb7041Schristos 
2131*56bb7041Schristos static void
write_rc_resource(FILE * e,const rc_res_id * type,const rc_res_id * name,const rc_res_resource * res,rc_uint_type * language)2132*56bb7041Schristos write_rc_resource (FILE *e, const rc_res_id *type,
2133*56bb7041Schristos 		   const rc_res_id *name, const rc_res_resource *res,
2134*56bb7041Schristos 		   rc_uint_type *language)
2135*56bb7041Schristos {
2136*56bb7041Schristos   const char *s;
2137*56bb7041Schristos   int rt;
2138*56bb7041Schristos   int menuex = 0;
2139*56bb7041Schristos 
2140*56bb7041Schristos   switch (res->type)
2141*56bb7041Schristos     {
2142*56bb7041Schristos     default:
2143*56bb7041Schristos       abort ();
2144*56bb7041Schristos 
2145*56bb7041Schristos     case RES_TYPE_ACCELERATOR:
2146*56bb7041Schristos       s = "ACCELERATORS";
2147*56bb7041Schristos       rt = RT_ACCELERATOR;
2148*56bb7041Schristos       break;
2149*56bb7041Schristos 
2150*56bb7041Schristos     case RES_TYPE_BITMAP:
2151*56bb7041Schristos       s = "2 /* RT_BITMAP */";
2152*56bb7041Schristos       rt = RT_BITMAP;
2153*56bb7041Schristos       break;
2154*56bb7041Schristos 
2155*56bb7041Schristos     case RES_TYPE_CURSOR:
2156*56bb7041Schristos       s = "1 /* RT_CURSOR */";
2157*56bb7041Schristos       rt = RT_CURSOR;
2158*56bb7041Schristos       break;
2159*56bb7041Schristos 
2160*56bb7041Schristos     case RES_TYPE_GROUP_CURSOR:
2161*56bb7041Schristos       s = "12 /* RT_GROUP_CURSOR */";
2162*56bb7041Schristos       rt = RT_GROUP_CURSOR;
2163*56bb7041Schristos       break;
2164*56bb7041Schristos 
2165*56bb7041Schristos     case RES_TYPE_DIALOG:
2166*56bb7041Schristos       if (extended_dialog (res->u.dialog))
2167*56bb7041Schristos 	s = "DIALOGEX";
2168*56bb7041Schristos       else
2169*56bb7041Schristos 	s = "DIALOG";
2170*56bb7041Schristos       rt = RT_DIALOG;
2171*56bb7041Schristos       break;
2172*56bb7041Schristos 
2173*56bb7041Schristos     case RES_TYPE_FONT:
2174*56bb7041Schristos       s = "8 /* RT_FONT */";
2175*56bb7041Schristos       rt = RT_FONT;
2176*56bb7041Schristos       break;
2177*56bb7041Schristos 
2178*56bb7041Schristos     case RES_TYPE_FONTDIR:
2179*56bb7041Schristos       s = "7 /* RT_FONTDIR */";
2180*56bb7041Schristos       rt = RT_FONTDIR;
2181*56bb7041Schristos       break;
2182*56bb7041Schristos 
2183*56bb7041Schristos     case RES_TYPE_ICON:
2184*56bb7041Schristos       s = "3 /* RT_ICON */";
2185*56bb7041Schristos       rt = RT_ICON;
2186*56bb7041Schristos       break;
2187*56bb7041Schristos 
2188*56bb7041Schristos     case RES_TYPE_GROUP_ICON:
2189*56bb7041Schristos       s = "14 /* RT_GROUP_ICON */";
2190*56bb7041Schristos       rt = RT_GROUP_ICON;
2191*56bb7041Schristos       break;
2192*56bb7041Schristos 
2193*56bb7041Schristos     case RES_TYPE_MENU:
2194*56bb7041Schristos       if (extended_menu (res->u.menu))
2195*56bb7041Schristos 	{
2196*56bb7041Schristos 	  s = "MENUEX";
2197*56bb7041Schristos 	  menuex = 1;
2198*56bb7041Schristos 	}
2199*56bb7041Schristos       else
2200*56bb7041Schristos 	{
2201*56bb7041Schristos 	  s = "MENU";
2202*56bb7041Schristos 	  menuex = 0;
2203*56bb7041Schristos 	}
2204*56bb7041Schristos       rt = RT_MENU;
2205*56bb7041Schristos       break;
2206*56bb7041Schristos 
2207*56bb7041Schristos     case RES_TYPE_MESSAGETABLE:
2208*56bb7041Schristos       s = "11 /* RT_MESSAGETABLE */";
2209*56bb7041Schristos       rt = RT_MESSAGETABLE;
2210*56bb7041Schristos       break;
2211*56bb7041Schristos 
2212*56bb7041Schristos     case RES_TYPE_RCDATA:
2213*56bb7041Schristos       s = "RCDATA";
2214*56bb7041Schristos       rt = RT_RCDATA;
2215*56bb7041Schristos       break;
2216*56bb7041Schristos 
2217*56bb7041Schristos     case RES_TYPE_STRINGTABLE:
2218*56bb7041Schristos       s = "STRINGTABLE";
2219*56bb7041Schristos       rt = RT_STRING;
2220*56bb7041Schristos       break;
2221*56bb7041Schristos 
2222*56bb7041Schristos     case RES_TYPE_USERDATA:
2223*56bb7041Schristos       s = NULL;
2224*56bb7041Schristos       rt = 0;
2225*56bb7041Schristos       break;
2226*56bb7041Schristos 
2227*56bb7041Schristos     case RES_TYPE_VERSIONINFO:
2228*56bb7041Schristos       s = "VERSIONINFO";
2229*56bb7041Schristos       rt = RT_VERSION;
2230*56bb7041Schristos       break;
2231*56bb7041Schristos 
2232*56bb7041Schristos     case RES_TYPE_TOOLBAR:
2233*56bb7041Schristos       s = "TOOLBAR";
2234*56bb7041Schristos       rt = RT_TOOLBAR;
2235*56bb7041Schristos       break;
2236*56bb7041Schristos     }
2237*56bb7041Schristos 
2238*56bb7041Schristos   if (rt != 0
2239*56bb7041Schristos       && type != NULL
2240*56bb7041Schristos       && (type->named || type->u.id != (unsigned long) rt))
2241*56bb7041Schristos     {
2242*56bb7041Schristos       wr_printcomment (e, "Unexpected resource type mismatch: ");
2243*56bb7041Schristos       res_id_print (e, *type, 1);
2244*56bb7041Schristos       fprintf (e, " != %d", rt);
2245*56bb7041Schristos     }
2246*56bb7041Schristos 
2247*56bb7041Schristos   if (res->coff_info.codepage != 0)
2248*56bb7041Schristos     wr_printcomment (e, "Code page: %u", res->coff_info.codepage);
2249*56bb7041Schristos   if (res->coff_info.reserved != 0)
2250*56bb7041Schristos     wr_printcomment (e, "COFF reserved value: %u", res->coff_info.reserved);
2251*56bb7041Schristos 
2252*56bb7041Schristos   wr_print (e, "\n");
2253*56bb7041Schristos   if (rt == RT_STRING)
2254*56bb7041Schristos     ;
2255*56bb7041Schristos   else
2256*56bb7041Schristos     {
2257*56bb7041Schristos   if (name != NULL)
2258*56bb7041Schristos 	res_id_print (e, *name, 1);
2259*56bb7041Schristos   else
2260*56bb7041Schristos     fprintf (e, "??Unknown-Name??");
2261*56bb7041Schristos   fprintf (e, " ");
2262*56bb7041Schristos     }
2263*56bb7041Schristos 
2264*56bb7041Schristos   if (s != NULL)
2265*56bb7041Schristos     fprintf (e, "%s", s);
2266*56bb7041Schristos   else if (type != NULL)
2267*56bb7041Schristos     {
2268*56bb7041Schristos       if (type->named == 0)
2269*56bb7041Schristos 	{
2270*56bb7041Schristos #define PRINT_RT_NAME(NAME) case NAME: \
2271*56bb7041Schristos 	fprintf (e, "%u /* %s */", (unsigned int) NAME, #NAME); \
2272*56bb7041Schristos 	break
2273*56bb7041Schristos 
2274*56bb7041Schristos 	  switch (type->u.id)
2275*56bb7041Schristos 	    {
2276*56bb7041Schristos 	    default:
2277*56bb7041Schristos     res_id_print (e, *type, 0);
2278*56bb7041Schristos 	      break;
2279*56bb7041Schristos 
2280*56bb7041Schristos 	    PRINT_RT_NAME(RT_MANIFEST);
2281*56bb7041Schristos 	    PRINT_RT_NAME(RT_ANICURSOR);
2282*56bb7041Schristos 	    PRINT_RT_NAME(RT_ANIICON);
2283*56bb7041Schristos 	    PRINT_RT_NAME(RT_RCDATA);
2284*56bb7041Schristos 	    PRINT_RT_NAME(RT_ICON);
2285*56bb7041Schristos 	    PRINT_RT_NAME(RT_CURSOR);
2286*56bb7041Schristos 	    PRINT_RT_NAME(RT_BITMAP);
2287*56bb7041Schristos 	    PRINT_RT_NAME(RT_PLUGPLAY);
2288*56bb7041Schristos 	    PRINT_RT_NAME(RT_VXD);
2289*56bb7041Schristos 	    PRINT_RT_NAME(RT_FONT);
2290*56bb7041Schristos 	    PRINT_RT_NAME(RT_FONTDIR);
2291*56bb7041Schristos 	    PRINT_RT_NAME(RT_HTML);
2292*56bb7041Schristos 	    PRINT_RT_NAME(RT_MESSAGETABLE);
2293*56bb7041Schristos 	    PRINT_RT_NAME(RT_DLGINCLUDE);
2294*56bb7041Schristos 	    PRINT_RT_NAME(RT_DLGINIT);
2295*56bb7041Schristos 	    }
2296*56bb7041Schristos #undef PRINT_RT_NAME
2297*56bb7041Schristos 	}
2298*56bb7041Schristos       else
2299*56bb7041Schristos 	res_id_print (e, *type, 1);
2300*56bb7041Schristos     }
2301*56bb7041Schristos   else
2302*56bb7041Schristos     fprintf (e, "??Unknown-Type??");
2303*56bb7041Schristos 
2304*56bb7041Schristos   if (res->res_info.memflags != 0)
2305*56bb7041Schristos     {
2306*56bb7041Schristos       if ((res->res_info.memflags & MEMFLAG_MOVEABLE) != 0)
2307*56bb7041Schristos 	fprintf (e, " MOVEABLE");
2308*56bb7041Schristos       if ((res->res_info.memflags & MEMFLAG_PURE) != 0)
2309*56bb7041Schristos 	fprintf (e, " PURE");
2310*56bb7041Schristos       if ((res->res_info.memflags & MEMFLAG_PRELOAD) != 0)
2311*56bb7041Schristos 	fprintf (e, " PRELOAD");
2312*56bb7041Schristos       if ((res->res_info.memflags & MEMFLAG_DISCARDABLE) != 0)
2313*56bb7041Schristos 	fprintf (e, " DISCARDABLE");
2314*56bb7041Schristos     }
2315*56bb7041Schristos 
2316*56bb7041Schristos   if (res->type == RES_TYPE_DIALOG)
2317*56bb7041Schristos     {
2318*56bb7041Schristos       fprintf (e, " %d, %d, %d, %d",
2319*56bb7041Schristos 	       (int) res->u.dialog->x, (int) res->u.dialog->y,
2320*56bb7041Schristos 	       (int) res->u.dialog->width, (int) res->u.dialog->height);
2321*56bb7041Schristos       if (res->u.dialog->ex != NULL
2322*56bb7041Schristos 	  && res->u.dialog->ex->help != 0)
2323*56bb7041Schristos 	fprintf (e, ", %u", (unsigned int) res->u.dialog->ex->help);
2324*56bb7041Schristos     }
2325*56bb7041Schristos   else if (res->type == RES_TYPE_TOOLBAR)
2326*56bb7041Schristos   {
2327*56bb7041Schristos     fprintf (e, " %d, %d", (int) res->u.toolbar->button_width,
2328*56bb7041Schristos 	     (int) res->u.toolbar->button_height);
2329*56bb7041Schristos     }
2330*56bb7041Schristos 
2331*56bb7041Schristos   fprintf (e, "\n");
2332*56bb7041Schristos 
2333*56bb7041Schristos   if ((res->res_info.language != 0 && res->res_info.language != *language)
2334*56bb7041Schristos       || res->res_info.characteristics != 0
2335*56bb7041Schristos       || res->res_info.version != 0)
2336*56bb7041Schristos     {
2337*56bb7041Schristos       int modifiers;
2338*56bb7041Schristos 
2339*56bb7041Schristos       switch (res->type)
2340*56bb7041Schristos 	{
2341*56bb7041Schristos 	case RES_TYPE_ACCELERATOR:
2342*56bb7041Schristos 	case RES_TYPE_DIALOG:
2343*56bb7041Schristos 	case RES_TYPE_MENU:
2344*56bb7041Schristos 	case RES_TYPE_RCDATA:
2345*56bb7041Schristos 	case RES_TYPE_STRINGTABLE:
2346*56bb7041Schristos 	  modifiers = 1;
2347*56bb7041Schristos 	  break;
2348*56bb7041Schristos 
2349*56bb7041Schristos 	default:
2350*56bb7041Schristos 	  modifiers = 0;
2351*56bb7041Schristos 	  break;
2352*56bb7041Schristos 	}
2353*56bb7041Schristos 
2354*56bb7041Schristos       if (res->res_info.language != 0 && res->res_info.language != *language)
2355*56bb7041Schristos 	fprintf (e, "%sLANGUAGE %d, %d\n",
2356*56bb7041Schristos 		 modifiers ? "// " : "",
2357*56bb7041Schristos 		 (int) res->res_info.language & ((1<<SUBLANG_SHIFT)-1),
2358*56bb7041Schristos 		 (int) (res->res_info.language >> SUBLANG_SHIFT) & 0xff);
2359*56bb7041Schristos       if (res->res_info.characteristics != 0)
2360*56bb7041Schristos 	fprintf (e, "%sCHARACTERISTICS %u\n",
2361*56bb7041Schristos 		 modifiers ? "// " : "",
2362*56bb7041Schristos 		 (unsigned int) res->res_info.characteristics);
2363*56bb7041Schristos       if (res->res_info.version != 0)
2364*56bb7041Schristos 	fprintf (e, "%sVERSION %u\n",
2365*56bb7041Schristos 		 modifiers ? "// " : "",
2366*56bb7041Schristos 		 (unsigned int) res->res_info.version);
2367*56bb7041Schristos     }
2368*56bb7041Schristos 
2369*56bb7041Schristos   switch (res->type)
2370*56bb7041Schristos     {
2371*56bb7041Schristos     default:
2372*56bb7041Schristos       abort ();
2373*56bb7041Schristos 
2374*56bb7041Schristos     case RES_TYPE_ACCELERATOR:
2375*56bb7041Schristos       write_rc_accelerators (e, res->u.acc);
2376*56bb7041Schristos       break;
2377*56bb7041Schristos 
2378*56bb7041Schristos     case RES_TYPE_CURSOR:
2379*56bb7041Schristos       write_rc_cursor (e, res->u.cursor);
2380*56bb7041Schristos       break;
2381*56bb7041Schristos 
2382*56bb7041Schristos     case RES_TYPE_GROUP_CURSOR:
2383*56bb7041Schristos       write_rc_group_cursor (e, res->u.group_cursor);
2384*56bb7041Schristos       break;
2385*56bb7041Schristos 
2386*56bb7041Schristos     case RES_TYPE_DIALOG:
2387*56bb7041Schristos       write_rc_dialog (e, res->u.dialog);
2388*56bb7041Schristos       break;
2389*56bb7041Schristos 
2390*56bb7041Schristos     case RES_TYPE_FONTDIR:
2391*56bb7041Schristos       write_rc_fontdir (e, res->u.fontdir);
2392*56bb7041Schristos       break;
2393*56bb7041Schristos 
2394*56bb7041Schristos     case RES_TYPE_GROUP_ICON:
2395*56bb7041Schristos       write_rc_group_icon (e, res->u.group_icon);
2396*56bb7041Schristos       break;
2397*56bb7041Schristos 
2398*56bb7041Schristos     case RES_TYPE_MENU:
2399*56bb7041Schristos       write_rc_menu (e, res->u.menu, menuex);
2400*56bb7041Schristos       break;
2401*56bb7041Schristos 
2402*56bb7041Schristos     case RES_TYPE_RCDATA:
2403*56bb7041Schristos       write_rc_rcdata (e, res->u.rcdata, 0);
2404*56bb7041Schristos       break;
2405*56bb7041Schristos 
2406*56bb7041Schristos     case RES_TYPE_STRINGTABLE:
2407*56bb7041Schristos       write_rc_stringtable (e, name, res->u.stringtable);
2408*56bb7041Schristos       break;
2409*56bb7041Schristos 
2410*56bb7041Schristos     case RES_TYPE_USERDATA:
2411*56bb7041Schristos       write_rc_rcdata (e, res->u.userdata, 0);
2412*56bb7041Schristos       break;
2413*56bb7041Schristos 
2414*56bb7041Schristos     case RES_TYPE_TOOLBAR:
2415*56bb7041Schristos       write_rc_toolbar (e, res->u.toolbar);
2416*56bb7041Schristos       break;
2417*56bb7041Schristos 
2418*56bb7041Schristos     case RES_TYPE_VERSIONINFO:
2419*56bb7041Schristos       write_rc_versioninfo (e, res->u.versioninfo);
2420*56bb7041Schristos       break;
2421*56bb7041Schristos 
2422*56bb7041Schristos     case RES_TYPE_BITMAP:
2423*56bb7041Schristos     case RES_TYPE_FONT:
2424*56bb7041Schristos     case RES_TYPE_ICON:
2425*56bb7041Schristos       write_rc_datablock (e, res->u.data.length, res->u.data.data, 0, 1, 0);
2426*56bb7041Schristos       break;
2427*56bb7041Schristos     case RES_TYPE_MESSAGETABLE:
2428*56bb7041Schristos       write_rc_messagetable (e, res->u.data.length, res->u.data.data);
2429*56bb7041Schristos       break;
2430*56bb7041Schristos     }
2431*56bb7041Schristos }
2432*56bb7041Schristos 
2433*56bb7041Schristos /* Write out accelerator information.  */
2434*56bb7041Schristos 
2435*56bb7041Schristos static void
write_rc_accelerators(FILE * e,const rc_accelerator * accelerators)2436*56bb7041Schristos write_rc_accelerators (FILE *e, const rc_accelerator *accelerators)
2437*56bb7041Schristos {
2438*56bb7041Schristos   const rc_accelerator *acc;
2439*56bb7041Schristos 
2440*56bb7041Schristos   fprintf (e, "BEGIN\n");
2441*56bb7041Schristos   for (acc = accelerators; acc != NULL; acc = acc->next)
2442*56bb7041Schristos     {
2443*56bb7041Schristos       int printable;
2444*56bb7041Schristos 
2445*56bb7041Schristos       fprintf (e, "  ");
2446*56bb7041Schristos 
2447*56bb7041Schristos       if ((acc->key & 0x7f) == acc->key
2448*56bb7041Schristos 	  && ISPRINT (acc->key)
2449*56bb7041Schristos 	  && (acc->flags & ACC_VIRTKEY) == 0)
2450*56bb7041Schristos 	{
2451*56bb7041Schristos 	  fprintf (e, "\"%c\"", (char) acc->key);
2452*56bb7041Schristos 	  printable = 1;
2453*56bb7041Schristos 	}
2454*56bb7041Schristos       else
2455*56bb7041Schristos 	{
2456*56bb7041Schristos 	  fprintf (e, "%d", (int) acc->key);
2457*56bb7041Schristos 	  printable = 0;
2458*56bb7041Schristos 	}
2459*56bb7041Schristos 
2460*56bb7041Schristos       fprintf (e, ", %d", (int) acc->id);
2461*56bb7041Schristos 
2462*56bb7041Schristos       if (! printable)
2463*56bb7041Schristos 	{
2464*56bb7041Schristos 	  if ((acc->flags & ACC_VIRTKEY) != 0)
2465*56bb7041Schristos 	    fprintf (e, ", VIRTKEY");
2466*56bb7041Schristos 	  else
2467*56bb7041Schristos 	    fprintf (e, ", ASCII");
2468*56bb7041Schristos 	}
2469*56bb7041Schristos 
2470*56bb7041Schristos       if ((acc->flags & ACC_SHIFT) != 0)
2471*56bb7041Schristos 	fprintf (e, ", SHIFT");
2472*56bb7041Schristos       if ((acc->flags & ACC_CONTROL) != 0)
2473*56bb7041Schristos 	fprintf (e, ", CONTROL");
2474*56bb7041Schristos       if ((acc->flags & ACC_ALT) != 0)
2475*56bb7041Schristos 	fprintf (e, ", ALT");
2476*56bb7041Schristos 
2477*56bb7041Schristos       fprintf (e, "\n");
2478*56bb7041Schristos     }
2479*56bb7041Schristos 
2480*56bb7041Schristos   fprintf (e, "END\n");
2481*56bb7041Schristos }
2482*56bb7041Schristos 
2483*56bb7041Schristos /* Write out cursor information.  This would normally be in a separate
2484*56bb7041Schristos    file, which the rc file would include.  */
2485*56bb7041Schristos 
2486*56bb7041Schristos static void
write_rc_cursor(FILE * e,const rc_cursor * cursor)2487*56bb7041Schristos write_rc_cursor (FILE *e, const rc_cursor *cursor)
2488*56bb7041Schristos {
2489*56bb7041Schristos   fprintf (e, "BEGIN\n");
2490*56bb7041Schristos   indent (e, 2);
2491*56bb7041Schristos   fprintf (e, " 0x%x, 0x%x,\t/* Hotspot x: %d, y: %d.  */\n",
2492*56bb7041Schristos 	   (unsigned int) cursor->xhotspot, (unsigned int) cursor->yhotspot,
2493*56bb7041Schristos 	   (int) cursor->xhotspot, (int) cursor->yhotspot);
2494*56bb7041Schristos   write_rc_datablock (e, (rc_uint_type) cursor->length, (const bfd_byte *) cursor->data,
2495*56bb7041Schristos   		      0, 0, 0);
2496*56bb7041Schristos   fprintf (e, "END\n");
2497*56bb7041Schristos }
2498*56bb7041Schristos 
2499*56bb7041Schristos /* Write out group cursor data.  This would normally be built from the
2500*56bb7041Schristos    cursor data.  */
2501*56bb7041Schristos 
2502*56bb7041Schristos static void
write_rc_group_cursor(FILE * e,const rc_group_cursor * group_cursor)2503*56bb7041Schristos write_rc_group_cursor (FILE *e, const rc_group_cursor *group_cursor)
2504*56bb7041Schristos {
2505*56bb7041Schristos   const rc_group_cursor *gc;
2506*56bb7041Schristos   int c;
2507*56bb7041Schristos 
2508*56bb7041Schristos   for (c = 0, gc = group_cursor; gc != NULL; gc = gc->next, c++)
2509*56bb7041Schristos     ;
2510*56bb7041Schristos   fprintf (e, "BEGIN\n");
2511*56bb7041Schristos 
2512*56bb7041Schristos   indent (e, 2);
2513*56bb7041Schristos   fprintf (e, "0, 2, %d%s\t /* Having %d items.  */\n", c, (c != 0 ? "," : ""), c);
2514*56bb7041Schristos   indent (e, 4);
2515*56bb7041Schristos   fprintf (e, "/* width, height, planes, bits, bytes, index.  */\n");
2516*56bb7041Schristos 
2517*56bb7041Schristos   for (c = 1, gc = group_cursor; gc != NULL; gc = gc->next, c++)
2518*56bb7041Schristos     {
2519*56bb7041Schristos       indent (e, 4);
2520*56bb7041Schristos       fprintf (e, "%d, %d, %d, %d, 0x%xL, %d%s /* Element %d. */\n",
2521*56bb7041Schristos 	(int) gc->width, (int) gc->height, (int) gc->planes, (int) gc->bits,
2522*56bb7041Schristos 	(unsigned int) gc->bytes, (int) gc->index, (gc->next != NULL ? "," : ""), c);
2523*56bb7041Schristos       fprintf (e, "/* width: %d; height %d; planes %d; bits %d.  */\n",
2524*56bb7041Schristos 	     (int) gc->width, (int) gc->height, (int) gc->planes,
2525*56bb7041Schristos 	     (int) gc->bits);
2526*56bb7041Schristos     }
2527*56bb7041Schristos   fprintf (e, "END\n");
2528*56bb7041Schristos }
2529*56bb7041Schristos 
2530*56bb7041Schristos /* Write dialog data.  */
2531*56bb7041Schristos 
2532*56bb7041Schristos static void
write_rc_dialog(FILE * e,const rc_dialog * dialog)2533*56bb7041Schristos write_rc_dialog (FILE *e, const rc_dialog *dialog)
2534*56bb7041Schristos {
2535*56bb7041Schristos   const rc_dialog_control *control;
2536*56bb7041Schristos 
2537*56bb7041Schristos   fprintf (e, "STYLE 0x%x\n", dialog->style);
2538*56bb7041Schristos 
2539*56bb7041Schristos   if (dialog->exstyle != 0)
2540*56bb7041Schristos     fprintf (e, "EXSTYLE 0x%x\n", (unsigned int) dialog->exstyle);
2541*56bb7041Schristos 
2542*56bb7041Schristos   if ((dialog->class.named && dialog->class.u.n.length > 0)
2543*56bb7041Schristos       || dialog->class.u.id != 0)
2544*56bb7041Schristos     {
2545*56bb7041Schristos       fprintf (e, "CLASS ");
2546*56bb7041Schristos       res_id_print (e, dialog->class, 1);
2547*56bb7041Schristos       fprintf (e, "\n");
2548*56bb7041Schristos     }
2549*56bb7041Schristos 
2550*56bb7041Schristos   if (dialog->caption != NULL)
2551*56bb7041Schristos     {
2552*56bb7041Schristos       fprintf (e, "CAPTION ");
2553*56bb7041Schristos       unicode_print_quoted (e, dialog->caption, -1);
2554*56bb7041Schristos       fprintf (e, "\n");
2555*56bb7041Schristos     }
2556*56bb7041Schristos 
2557*56bb7041Schristos   if ((dialog->menu.named && dialog->menu.u.n.length > 0)
2558*56bb7041Schristos       || dialog->menu.u.id != 0)
2559*56bb7041Schristos     {
2560*56bb7041Schristos       fprintf (e, "MENU ");
2561*56bb7041Schristos       res_id_print (e, dialog->menu, 0);
2562*56bb7041Schristos       fprintf (e, "\n");
2563*56bb7041Schristos     }
2564*56bb7041Schristos 
2565*56bb7041Schristos   if (dialog->font != NULL)
2566*56bb7041Schristos     {
2567*56bb7041Schristos       fprintf (e, "FONT %d, ", (int) dialog->pointsize);
2568*56bb7041Schristos       unicode_print_quoted (e, dialog->font, -1);
2569*56bb7041Schristos       if (dialog->ex != NULL
2570*56bb7041Schristos 	  && (dialog->ex->weight != 0
2571*56bb7041Schristos 	      || dialog->ex->italic != 0
2572*56bb7041Schristos 	      || dialog->ex->charset != 1))
2573*56bb7041Schristos 	fprintf (e, ", %d, %d, %d",
2574*56bb7041Schristos 		 (int) dialog->ex->weight,
2575*56bb7041Schristos 		 (int) dialog->ex->italic,
2576*56bb7041Schristos 		 (int) dialog->ex->charset);
2577*56bb7041Schristos       fprintf (e, "\n");
2578*56bb7041Schristos     }
2579*56bb7041Schristos 
2580*56bb7041Schristos   fprintf (e, "BEGIN\n");
2581*56bb7041Schristos 
2582*56bb7041Schristos   for (control = dialog->controls; control != NULL; control = control->next)
2583*56bb7041Schristos     write_rc_dialog_control (e, control);
2584*56bb7041Schristos 
2585*56bb7041Schristos   fprintf (e, "END\n");
2586*56bb7041Schristos }
2587*56bb7041Schristos 
2588*56bb7041Schristos /* For each predefined control keyword, this table provides the class
2589*56bb7041Schristos    and the style.  */
2590*56bb7041Schristos 
2591*56bb7041Schristos struct control_info
2592*56bb7041Schristos {
2593*56bb7041Schristos   const char *name;
2594*56bb7041Schristos   unsigned short class;
2595*56bb7041Schristos   unsigned long style;
2596*56bb7041Schristos };
2597*56bb7041Schristos 
2598*56bb7041Schristos static const struct control_info control_info[] =
2599*56bb7041Schristos {
2600*56bb7041Schristos   { "AUTO3STATE", CTL_BUTTON, BS_AUTO3STATE },
2601*56bb7041Schristos   { "AUTOCHECKBOX", CTL_BUTTON, BS_AUTOCHECKBOX },
2602*56bb7041Schristos   { "AUTORADIOBUTTON", CTL_BUTTON, BS_AUTORADIOBUTTON },
2603*56bb7041Schristos   { "CHECKBOX", CTL_BUTTON, BS_CHECKBOX },
2604*56bb7041Schristos   { "COMBOBOX", CTL_COMBOBOX, (unsigned long) -1 },
2605*56bb7041Schristos   { "CTEXT", CTL_STATIC, SS_CENTER },
2606*56bb7041Schristos   { "DEFPUSHBUTTON", CTL_BUTTON, BS_DEFPUSHBUTTON },
2607*56bb7041Schristos   { "EDITTEXT", CTL_EDIT, (unsigned long) -1 },
2608*56bb7041Schristos   { "GROUPBOX", CTL_BUTTON, BS_GROUPBOX },
2609*56bb7041Schristos   { "ICON", CTL_STATIC, SS_ICON },
2610*56bb7041Schristos   { "LISTBOX", CTL_LISTBOX, (unsigned long) -1 },
2611*56bb7041Schristos   { "LTEXT", CTL_STATIC, SS_LEFT },
2612*56bb7041Schristos   { "PUSHBOX", CTL_BUTTON, BS_PUSHBOX },
2613*56bb7041Schristos   { "PUSHBUTTON", CTL_BUTTON, BS_PUSHBUTTON },
2614*56bb7041Schristos   { "RADIOBUTTON", CTL_BUTTON, BS_RADIOBUTTON },
2615*56bb7041Schristos   { "RTEXT", CTL_STATIC, SS_RIGHT },
2616*56bb7041Schristos   { "SCROLLBAR", CTL_SCROLLBAR, (unsigned long) -1 },
2617*56bb7041Schristos   { "STATE3", CTL_BUTTON, BS_3STATE },
2618*56bb7041Schristos   /* It's important that USERBUTTON come after all the other button
2619*56bb7041Schristos      types, so that it won't be matched too early.  */
2620*56bb7041Schristos   { "USERBUTTON", CTL_BUTTON, (unsigned long) -1 },
2621*56bb7041Schristos   { NULL, 0, 0 }
2622*56bb7041Schristos };
2623*56bb7041Schristos 
2624*56bb7041Schristos /* Write a dialog control.  */
2625*56bb7041Schristos 
2626*56bb7041Schristos static void
write_rc_dialog_control(FILE * e,const rc_dialog_control * control)2627*56bb7041Schristos write_rc_dialog_control (FILE *e, const rc_dialog_control *control)
2628*56bb7041Schristos {
2629*56bb7041Schristos   const struct control_info *ci;
2630*56bb7041Schristos 
2631*56bb7041Schristos   fprintf (e, "  ");
2632*56bb7041Schristos 
2633*56bb7041Schristos   if (control->class.named)
2634*56bb7041Schristos     ci = NULL;
2635*56bb7041Schristos   else
2636*56bb7041Schristos     {
2637*56bb7041Schristos       for (ci = control_info; ci->name != NULL; ++ci)
2638*56bb7041Schristos 	if (ci->class == control->class.u.id
2639*56bb7041Schristos 	    && (ci->style == (unsigned long) -1
2640*56bb7041Schristos 		|| ci->style == (control->style & 0xff)))
2641*56bb7041Schristos 	  break;
2642*56bb7041Schristos     }
2643*56bb7041Schristos   if (ci == NULL)
2644*56bb7041Schristos     fprintf (e, "CONTROL");
2645*56bb7041Schristos   else if (ci->name != NULL)
2646*56bb7041Schristos     fprintf (e, "%s", ci->name);
2647*56bb7041Schristos   else
2648*56bb7041Schristos     {
2649*56bb7041Schristos     fprintf (e, "CONTROL");
2650*56bb7041Schristos       ci = NULL;
2651*56bb7041Schristos     }
2652*56bb7041Schristos 
2653*56bb7041Schristos   /* For EDITTEXT, COMBOBOX, LISTBOX, and SCROLLBAR don't dump text.  */
2654*56bb7041Schristos   if ((control->text.named || control->text.u.id != 0)
2655*56bb7041Schristos       && (!ci
2656*56bb7041Schristos           || (ci->class != CTL_EDIT
2657*56bb7041Schristos               && ci->class != CTL_COMBOBOX
2658*56bb7041Schristos               && ci->class != CTL_LISTBOX
2659*56bb7041Schristos               && ci->class != CTL_SCROLLBAR)))
2660*56bb7041Schristos     {
2661*56bb7041Schristos       fprintf (e, " ");
2662*56bb7041Schristos       res_id_print (e, control->text, 1);
2663*56bb7041Schristos       fprintf (e, ",");
2664*56bb7041Schristos     }
2665*56bb7041Schristos 
2666*56bb7041Schristos   fprintf (e, " %d, ", (int) control->id);
2667*56bb7041Schristos 
2668*56bb7041Schristos   if (ci == NULL)
2669*56bb7041Schristos     {
2670*56bb7041Schristos       if (control->class.named)
2671*56bb7041Schristos 	fprintf (e, "\"");
2672*56bb7041Schristos       res_id_print (e, control->class, 0);
2673*56bb7041Schristos       if (control->class.named)
2674*56bb7041Schristos 	fprintf (e, "\"");
2675*56bb7041Schristos       fprintf (e, ", 0x%x, ", (unsigned int) control->style);
2676*56bb7041Schristos     }
2677*56bb7041Schristos 
2678*56bb7041Schristos   fprintf (e, "%d, %d", (int) control->x, (int) control->y);
2679*56bb7041Schristos 
2680*56bb7041Schristos   if (control->style != SS_ICON
2681*56bb7041Schristos       || control->exstyle != 0
2682*56bb7041Schristos       || control->width != 0
2683*56bb7041Schristos       || control->height != 0
2684*56bb7041Schristos       || control->help != 0)
2685*56bb7041Schristos     {
2686*56bb7041Schristos       fprintf (e, ", %d, %d", (int) control->width, (int) control->height);
2687*56bb7041Schristos 
2688*56bb7041Schristos       /* FIXME: We don't need to print the style if it is the default.
2689*56bb7041Schristos 	 More importantly, in certain cases we actually need to turn
2690*56bb7041Schristos 	 off parts of the forced style, by using NOT.  */
2691*56bb7041Schristos       if (ci != NULL)
2692*56bb7041Schristos 	fprintf (e, ", 0x%x", (unsigned int) control->style);
2693*56bb7041Schristos 
2694*56bb7041Schristos       if (control->exstyle != 0 || control->help != 0)
2695*56bb7041Schristos 	fprintf (e, ", 0x%x, %u", (unsigned int) control->exstyle,
2696*56bb7041Schristos 		 (unsigned int) control->help);
2697*56bb7041Schristos     }
2698*56bb7041Schristos 
2699*56bb7041Schristos   fprintf (e, "\n");
2700*56bb7041Schristos 
2701*56bb7041Schristos   if (control->data != NULL)
2702*56bb7041Schristos     write_rc_rcdata (e, control->data, 2);
2703*56bb7041Schristos }
2704*56bb7041Schristos 
2705*56bb7041Schristos /* Write out font directory data.  This would normally be built from
2706*56bb7041Schristos    the font data.  */
2707*56bb7041Schristos 
2708*56bb7041Schristos static void
write_rc_fontdir(FILE * e,const rc_fontdir * fontdir)2709*56bb7041Schristos write_rc_fontdir (FILE *e, const rc_fontdir *fontdir)
2710*56bb7041Schristos {
2711*56bb7041Schristos   const rc_fontdir *fc;
2712*56bb7041Schristos   int c;
2713*56bb7041Schristos 
2714*56bb7041Schristos   for (c = 0, fc = fontdir; fc != NULL; fc = fc->next, c++)
2715*56bb7041Schristos     ;
2716*56bb7041Schristos   fprintf (e, "BEGIN\n");
2717*56bb7041Schristos   indent (e, 2);
2718*56bb7041Schristos   fprintf (e, "%d%s\t /* Has %d elements.  */\n", c, (c != 0 ? "," : ""), c);
2719*56bb7041Schristos   for (c = 1, fc = fontdir; fc != NULL; fc = fc->next, c++)
2720*56bb7041Schristos     {
2721*56bb7041Schristos       indent (e, 4);
2722*56bb7041Schristos       fprintf (e, "%d,\t/* Font no %d with index %d.  */\n",
2723*56bb7041Schristos 	(int) fc->index, c, (int) fc->index);
2724*56bb7041Schristos       write_rc_datablock (e, (rc_uint_type) fc->length - 2,
2725*56bb7041Schristos 			  (const bfd_byte *) fc->data + 4,fc->next != NULL,
2726*56bb7041Schristos 			  0, 0);
2727*56bb7041Schristos     }
2728*56bb7041Schristos   fprintf (e, "END\n");
2729*56bb7041Schristos }
2730*56bb7041Schristos 
2731*56bb7041Schristos /* Write out group icon data.  This would normally be built from the
2732*56bb7041Schristos    icon data.  */
2733*56bb7041Schristos 
2734*56bb7041Schristos static void
write_rc_group_icon(FILE * e,const rc_group_icon * group_icon)2735*56bb7041Schristos write_rc_group_icon (FILE *e, const rc_group_icon *group_icon)
2736*56bb7041Schristos {
2737*56bb7041Schristos   const rc_group_icon *gi;
2738*56bb7041Schristos   int c;
2739*56bb7041Schristos 
2740*56bb7041Schristos   for (c = 0, gi = group_icon; gi != NULL; gi = gi->next, c++)
2741*56bb7041Schristos     ;
2742*56bb7041Schristos 
2743*56bb7041Schristos   fprintf (e, "BEGIN\n");
2744*56bb7041Schristos   indent (e, 2);
2745*56bb7041Schristos   fprintf (e, " 0, 1, %d%s\t /* Has %d elements.  */\n", c, (c != 0 ? "," : ""), c);
2746*56bb7041Schristos 
2747*56bb7041Schristos   indent (e, 4);
2748*56bb7041Schristos   fprintf (e, "/* \"width height colors pad\", planes, bits, bytes, index.  */\n");
2749*56bb7041Schristos   for (c = 1, gi = group_icon; gi != NULL; gi = gi->next, c++)
2750*56bb7041Schristos     {
2751*56bb7041Schristos       indent (e, 4);
2752*56bb7041Schristos       fprintf (e, "\"\\%03o\\%03o\\%03o\\%03o\", %d, %d, 0x%xL, %d%s\t/* Element no %d.  */\n",
2753*56bb7041Schristos 	gi->width, gi->height, gi->colors, 0, (int) gi->planes, (int) gi->bits,
2754*56bb7041Schristos 	(unsigned int) gi->bytes, (int) gi->index, (gi->next != NULL ? "," : ""), c);
2755*56bb7041Schristos     }
2756*56bb7041Schristos   fprintf (e, "END\n");
2757*56bb7041Schristos }
2758*56bb7041Schristos 
2759*56bb7041Schristos /* Write out a menu resource.  */
2760*56bb7041Schristos 
2761*56bb7041Schristos static void
write_rc_menu(FILE * e,const rc_menu * menu,int menuex)2762*56bb7041Schristos write_rc_menu (FILE *e, const rc_menu *menu, int menuex)
2763*56bb7041Schristos {
2764*56bb7041Schristos   if (menu->help != 0)
2765*56bb7041Schristos     fprintf (e, "// Help ID: %u\n", (unsigned int) menu->help);
2766*56bb7041Schristos   write_rc_menuitems (e, menu->items, menuex, 0);
2767*56bb7041Schristos }
2768*56bb7041Schristos 
2769*56bb7041Schristos static void
write_rc_toolbar(FILE * e,const rc_toolbar * tb)2770*56bb7041Schristos write_rc_toolbar (FILE *e, const rc_toolbar *tb)
2771*56bb7041Schristos {
2772*56bb7041Schristos   rc_toolbar_item *it;
2773*56bb7041Schristos   indent (e, 0);
2774*56bb7041Schristos   fprintf (e, "BEGIN\n");
2775*56bb7041Schristos   it = tb->items;
2776*56bb7041Schristos   while(it != NULL)
2777*56bb7041Schristos   {
2778*56bb7041Schristos     indent (e, 2);
2779*56bb7041Schristos     if (it->id.u.id == 0)
2780*56bb7041Schristos       fprintf (e, "SEPARATOR\n");
2781*56bb7041Schristos     else
2782*56bb7041Schristos       fprintf (e, "BUTTON %d\n", (int) it->id.u.id);
2783*56bb7041Schristos     it = it->next;
2784*56bb7041Schristos   }
2785*56bb7041Schristos   indent (e, 0);
2786*56bb7041Schristos   fprintf (e, "END\n");
2787*56bb7041Schristos }
2788*56bb7041Schristos 
2789*56bb7041Schristos /* Write out menuitems.  */
2790*56bb7041Schristos 
2791*56bb7041Schristos static void
write_rc_menuitems(FILE * e,const rc_menuitem * menuitems,int menuex,int ind)2792*56bb7041Schristos write_rc_menuitems (FILE *e, const rc_menuitem *menuitems, int menuex,
2793*56bb7041Schristos 		    int ind)
2794*56bb7041Schristos {
2795*56bb7041Schristos   const rc_menuitem *mi;
2796*56bb7041Schristos 
2797*56bb7041Schristos   indent (e, ind);
2798*56bb7041Schristos   fprintf (e, "BEGIN\n");
2799*56bb7041Schristos 
2800*56bb7041Schristos   for (mi = menuitems; mi != NULL; mi = mi->next)
2801*56bb7041Schristos     {
2802*56bb7041Schristos       indent (e, ind + 2);
2803*56bb7041Schristos 
2804*56bb7041Schristos       if (mi->popup == NULL)
2805*56bb7041Schristos 	fprintf (e, "MENUITEM");
2806*56bb7041Schristos       else
2807*56bb7041Schristos 	fprintf (e, "POPUP");
2808*56bb7041Schristos 
2809*56bb7041Schristos       if (! menuex
2810*56bb7041Schristos 	  && mi->popup == NULL
2811*56bb7041Schristos 	  && mi->text == NULL
2812*56bb7041Schristos 	  && mi->type == 0
2813*56bb7041Schristos 	  && mi->id == 0)
2814*56bb7041Schristos 	{
2815*56bb7041Schristos 	  fprintf (e, " SEPARATOR\n");
2816*56bb7041Schristos 	  continue;
2817*56bb7041Schristos 	}
2818*56bb7041Schristos 
2819*56bb7041Schristos       if (mi->text == NULL)
2820*56bb7041Schristos 	fprintf (e, " \"\"");
2821*56bb7041Schristos       else
2822*56bb7041Schristos 	{
2823*56bb7041Schristos 	  fprintf (e, " ");
2824*56bb7041Schristos 	  unicode_print_quoted (e, mi->text, -1);
2825*56bb7041Schristos 	}
2826*56bb7041Schristos 
2827*56bb7041Schristos       if (! menuex)
2828*56bb7041Schristos 	{
2829*56bb7041Schristos 	  if (mi->popup == NULL)
2830*56bb7041Schristos 	    fprintf (e, ", %d", (int) mi->id);
2831*56bb7041Schristos 
2832*56bb7041Schristos 	  if ((mi->type & MENUITEM_CHECKED) != 0)
2833*56bb7041Schristos 	    fprintf (e, ", CHECKED");
2834*56bb7041Schristos 	  if ((mi->type & MENUITEM_GRAYED) != 0)
2835*56bb7041Schristos 	    fprintf (e, ", GRAYED");
2836*56bb7041Schristos 	  if ((mi->type & MENUITEM_HELP) != 0)
2837*56bb7041Schristos 	    fprintf (e, ", HELP");
2838*56bb7041Schristos 	  if ((mi->type & MENUITEM_INACTIVE) != 0)
2839*56bb7041Schristos 	    fprintf (e, ", INACTIVE");
2840*56bb7041Schristos 	  if ((mi->type & MENUITEM_MENUBARBREAK) != 0)
2841*56bb7041Schristos 	    fprintf (e, ", MENUBARBREAK");
2842*56bb7041Schristos 	  if ((mi->type & MENUITEM_MENUBREAK) != 0)
2843*56bb7041Schristos 	    fprintf (e, ", MENUBREAK");
2844*56bb7041Schristos 	  if ((mi->type & MENUITEM_OWNERDRAW) != 0)
2845*56bb7041Schristos 	    fprintf (e, ", OWNERDRAW");
2846*56bb7041Schristos 	  if ((mi->type & MENUITEM_BITMAP) != 0)
2847*56bb7041Schristos 	    fprintf (e, ", BITMAP");
2848*56bb7041Schristos 	}
2849*56bb7041Schristos       else
2850*56bb7041Schristos 	{
2851*56bb7041Schristos 	  if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0)
2852*56bb7041Schristos 	    {
2853*56bb7041Schristos 	      fprintf (e, ", %d", (int) mi->id);
2854*56bb7041Schristos 	      if (mi->type != 0 || mi->state != 0 || mi->help != 0)
2855*56bb7041Schristos 		{
2856*56bb7041Schristos 		  fprintf (e, ", %u", (unsigned int) mi->type);
2857*56bb7041Schristos 		  if (mi->state != 0 || mi->help != 0)
2858*56bb7041Schristos 		    {
2859*56bb7041Schristos 		      fprintf (e, ", %u", (unsigned int) mi->state);
2860*56bb7041Schristos 		      if (mi->help != 0)
2861*56bb7041Schristos 			fprintf (e, ", %u", (unsigned int) mi->help);
2862*56bb7041Schristos 		    }
2863*56bb7041Schristos 		}
2864*56bb7041Schristos 	    }
2865*56bb7041Schristos 	}
2866*56bb7041Schristos 
2867*56bb7041Schristos       fprintf (e, "\n");
2868*56bb7041Schristos 
2869*56bb7041Schristos       if (mi->popup != NULL)
2870*56bb7041Schristos 	write_rc_menuitems (e, mi->popup, menuex, ind + 2);
2871*56bb7041Schristos     }
2872*56bb7041Schristos 
2873*56bb7041Schristos   indent (e, ind);
2874*56bb7041Schristos   fprintf (e, "END\n");
2875*56bb7041Schristos }
2876*56bb7041Schristos 
2877*56bb7041Schristos static int
test_rc_datablock_unicode(rc_uint_type length,const bfd_byte * data)2878*56bb7041Schristos test_rc_datablock_unicode (rc_uint_type length, const bfd_byte *data)
2879*56bb7041Schristos {
2880*56bb7041Schristos   rc_uint_type i;
2881*56bb7041Schristos   if ((length & 1) != 0)
2882*56bb7041Schristos     return 0;
2883*56bb7041Schristos 
2884*56bb7041Schristos   for (i = 0; i < length; i += 2)
2885*56bb7041Schristos     {
2886*56bb7041Schristos       if (data[i] == 0 && data[i + 1] == 0 && (i + 2) < length)
2887*56bb7041Schristos 	return 0;
2888*56bb7041Schristos       if (data[i] == 0xff && data[i + 1] == 0xff)
2889*56bb7041Schristos 	return 0;
2890*56bb7041Schristos     }
2891*56bb7041Schristos   return 1;
2892*56bb7041Schristos }
2893*56bb7041Schristos 
2894*56bb7041Schristos static int
test_rc_datablock_text(rc_uint_type length,const bfd_byte * data)2895*56bb7041Schristos test_rc_datablock_text (rc_uint_type length, const bfd_byte *data)
2896*56bb7041Schristos {
2897*56bb7041Schristos   int has_nl;
2898*56bb7041Schristos   rc_uint_type c;
2899*56bb7041Schristos   rc_uint_type i;
2900*56bb7041Schristos 
2901*56bb7041Schristos   if (length <= 1)
2902*56bb7041Schristos     return 0;
2903*56bb7041Schristos 
2904*56bb7041Schristos   has_nl = 0;
2905*56bb7041Schristos   for (i = 0, c = 0; i < length; i++)
2906*56bb7041Schristos     {
2907*56bb7041Schristos       if (! ISPRINT (data[i]) && data[i] != '\n'
2908*56bb7041Schristos       	  && ! (data[i] == '\r' && (i + 1) < length && data[i + 1] == '\n')
2909*56bb7041Schristos       	  && data[i] != '\t'
2910*56bb7041Schristos 	  && ! (data[i] == 0 && (i + 1) != length))
2911*56bb7041Schristos 	{
2912*56bb7041Schristos 	  if (data[i] <= 7)
2913*56bb7041Schristos 	    return 0;
2914*56bb7041Schristos 	  c++;
2915*56bb7041Schristos 	}
2916*56bb7041Schristos       else if (data[i] == '\n') has_nl++;
2917*56bb7041Schristos     }
2918*56bb7041Schristos   if (length > 80 && ! has_nl)
2919*56bb7041Schristos     return 0;
2920*56bb7041Schristos   c = (((c * 10000) + (i / 100) - 1)) / i;
2921*56bb7041Schristos   if (c >= 150)
2922*56bb7041Schristos     return 0;
2923*56bb7041Schristos   return 1;
2924*56bb7041Schristos }
2925*56bb7041Schristos 
2926*56bb7041Schristos static void
write_rc_messagetable(FILE * e,rc_uint_type length,const bfd_byte * data)2927*56bb7041Schristos write_rc_messagetable (FILE *e, rc_uint_type length, const bfd_byte *data)
2928*56bb7041Schristos {
2929*56bb7041Schristos   int has_error = 0;
2930*56bb7041Schristos   const struct bin_messagetable *mt;
2931*56bb7041Schristos 
2932*56bb7041Schristos   fprintf (e, "BEGIN\n");
2933*56bb7041Schristos 
2934*56bb7041Schristos   write_rc_datablock (e, length, data, 0, 0, 0);
2935*56bb7041Schristos 
2936*56bb7041Schristos   fprintf (e, "\n");
2937*56bb7041Schristos   wr_printcomment (e, "MC syntax dump");
2938*56bb7041Schristos   if (length < BIN_MESSAGETABLE_SIZE)
2939*56bb7041Schristos     has_error = 1;
2940*56bb7041Schristos   else
2941*56bb7041Schristos     do
2942*56bb7041Schristos       {
2943*56bb7041Schristos 	rc_uint_type m, i;
2944*56bb7041Schristos 
2945*56bb7041Schristos 	mt = (const struct bin_messagetable *) data;
2946*56bb7041Schristos 	m = windres_get_32 (&wrtarget, mt->cblocks, length);
2947*56bb7041Schristos 
2948*56bb7041Schristos 	if (length < (BIN_MESSAGETABLE_SIZE + m * BIN_MESSAGETABLE_BLOCK_SIZE))
2949*56bb7041Schristos 	  {
2950*56bb7041Schristos 	    has_error = 1;
2951*56bb7041Schristos 	    break;
2952*56bb7041Schristos 	  }
2953*56bb7041Schristos 	for (i = 0; i < m; i++)
2954*56bb7041Schristos 	  {
2955*56bb7041Schristos 	    rc_uint_type low, high, offset;
2956*56bb7041Schristos 	    const struct bin_messagetable_item *mti;
2957*56bb7041Schristos 
2958*56bb7041Schristos 	    low = windres_get_32 (&wrtarget, mt->items[i].lowid, 4);
2959*56bb7041Schristos 	    high = windres_get_32 (&wrtarget, mt->items[i].highid, 4);
2960*56bb7041Schristos 	    offset = windres_get_32 (&wrtarget, mt->items[i].offset, 4);
2961*56bb7041Schristos 
2962*56bb7041Schristos 	    while (low <= high)
2963*56bb7041Schristos 	      {
2964*56bb7041Schristos 		rc_uint_type elen, flags;
2965*56bb7041Schristos 		if ((offset + BIN_MESSAGETABLE_ITEM_SIZE) > length)
2966*56bb7041Schristos 		  {
2967*56bb7041Schristos 		    has_error = 1;
2968*56bb7041Schristos 		    break;
2969*56bb7041Schristos 		  }
2970*56bb7041Schristos 		mti = (const struct bin_messagetable_item *) &data[offset];
2971*56bb7041Schristos 		elen = windres_get_16 (&wrtarget, mti->length, 2);
2972*56bb7041Schristos 		flags = windres_get_16 (&wrtarget, mti->flags, 2);
2973*56bb7041Schristos 		if ((offset + elen) > length)
2974*56bb7041Schristos 		  {
2975*56bb7041Schristos 		    has_error = 1;
2976*56bb7041Schristos 		    break;
2977*56bb7041Schristos 		  }
2978*56bb7041Schristos 		wr_printcomment (e, "MessageId = 0x%x", low);
2979*56bb7041Schristos 		wr_printcomment (e, "");
2980*56bb7041Schristos 
2981*56bb7041Schristos 		if ((flags & MESSAGE_RESOURCE_UNICODE) == MESSAGE_RESOURCE_UNICODE)
2982*56bb7041Schristos 		  {
2983*56bb7041Schristos 		    /* PR 17512: file: 5c3232dc.  */
2984*56bb7041Schristos 		    if (elen > BIN_MESSAGETABLE_ITEM_SIZE * 2)
2985*56bb7041Schristos 		      unicode_print (e, (const unichar *) mti->data,
2986*56bb7041Schristos 				     (elen - BIN_MESSAGETABLE_ITEM_SIZE) / 2);
2987*56bb7041Schristos 		  }
2988*56bb7041Schristos 		else
2989*56bb7041Schristos 		  {
2990*56bb7041Schristos 		    if (elen > BIN_MESSAGETABLE_ITEM_SIZE)
2991*56bb7041Schristos 		      ascii_print (e, (const char *) mti->data,
2992*56bb7041Schristos 				   (elen - BIN_MESSAGETABLE_ITEM_SIZE));
2993*56bb7041Schristos 		  }
2994*56bb7041Schristos 
2995*56bb7041Schristos 		wr_printcomment (e,"");
2996*56bb7041Schristos 		++low;
2997*56bb7041Schristos 		offset += elen;
2998*56bb7041Schristos 	      }
2999*56bb7041Schristos 	  }
3000*56bb7041Schristos       }
3001*56bb7041Schristos     while (0);
3002*56bb7041Schristos 
3003*56bb7041Schristos   if (has_error)
3004*56bb7041Schristos     wr_printcomment (e, "Illegal data");
3005*56bb7041Schristos   wr_print_flush (e);
3006*56bb7041Schristos   fprintf (e, "END\n");
3007*56bb7041Schristos }
3008*56bb7041Schristos 
3009*56bb7041Schristos static void
write_rc_datablock(FILE * e,rc_uint_type length,const bfd_byte * data,int has_next,int hasblock,int show_comment)3010*56bb7041Schristos write_rc_datablock (FILE *e, rc_uint_type length, const bfd_byte *data, int has_next,
3011*56bb7041Schristos 		    int hasblock, int show_comment)
3012*56bb7041Schristos {
3013*56bb7041Schristos   int plen;
3014*56bb7041Schristos 
3015*56bb7041Schristos   if (hasblock)
3016*56bb7041Schristos     fprintf (e, "BEGIN\n");
3017*56bb7041Schristos 
3018*56bb7041Schristos   if (show_comment == -1)
3019*56bb7041Schristos     {
3020*56bb7041Schristos       if (test_rc_datablock_text(length, data))
3021*56bb7041Schristos 	{
3022*56bb7041Schristos 	  rc_uint_type i, c;
3023*56bb7041Schristos 	  for (i = 0; i < length;)
3024*56bb7041Schristos 	    {
3025*56bb7041Schristos 	      indent (e, 2);
3026*56bb7041Schristos 	      fprintf (e, "\"");
3027*56bb7041Schristos 
3028*56bb7041Schristos 	      for (c = 0; i < length && c < 160 && data[i] != '\n'; c++, i++)
3029*56bb7041Schristos 		;
3030*56bb7041Schristos 	      if (i < length && data[i] == '\n')
3031*56bb7041Schristos 		++i, ++c;
3032*56bb7041Schristos 	      ascii_print(e, (const char *) &data[i - c], c);
3033*56bb7041Schristos 	    fprintf (e, "\"");
3034*56bb7041Schristos 	      if (i < length)
3035*56bb7041Schristos 		fprintf (e, "\n");
3036*56bb7041Schristos 	    }
3037*56bb7041Schristos 
3038*56bb7041Schristos 	  if (i == 0)
3039*56bb7041Schristos 	      {
3040*56bb7041Schristos 	      indent (e, 2);
3041*56bb7041Schristos 	      fprintf (e, "\"\"");
3042*56bb7041Schristos 	      }
3043*56bb7041Schristos 	  if (has_next)
3044*56bb7041Schristos 	    fprintf (e, ",");
3045*56bb7041Schristos 	  fprintf (e, "\n");
3046*56bb7041Schristos 	  if (hasblock)
3047*56bb7041Schristos 	    fprintf (e, "END\n");
3048*56bb7041Schristos 	  return;
3049*56bb7041Schristos 	  }
3050*56bb7041Schristos       if (test_rc_datablock_unicode (length, data))
3051*56bb7041Schristos 	{
3052*56bb7041Schristos 	  rc_uint_type i, c;
3053*56bb7041Schristos 	  for (i = 0; i < length;)
3054*56bb7041Schristos 	    {
3055*56bb7041Schristos 	      const unichar *u;
3056*56bb7041Schristos 
3057*56bb7041Schristos 	      u = (const unichar *) &data[i];
3058*56bb7041Schristos 	      indent (e, 2);
3059*56bb7041Schristos 	  fprintf (e, "L\"");
3060*56bb7041Schristos 
3061*56bb7041Schristos 	      for (c = 0; i < length && c < 160 && u[c] != '\n'; c++, i += 2)
3062*56bb7041Schristos 		;
3063*56bb7041Schristos 	      if (i < length && u[c] == '\n')
3064*56bb7041Schristos 		i += 2, ++c;
3065*56bb7041Schristos 	      unicode_print (e, u, c);
3066*56bb7041Schristos 	  fprintf (e, "\"");
3067*56bb7041Schristos 	      if (i < length)
3068*56bb7041Schristos 		fprintf (e, "\n");
3069*56bb7041Schristos 	    }
3070*56bb7041Schristos 
3071*56bb7041Schristos 	  if (i == 0)
3072*56bb7041Schristos 	  {
3073*56bb7041Schristos 	      indent (e, 2);
3074*56bb7041Schristos 	      fprintf (e, "L\"\"");
3075*56bb7041Schristos 	    }
3076*56bb7041Schristos 	  if (has_next)
3077*56bb7041Schristos 	    fprintf (e, ",");
3078*56bb7041Schristos 	  fprintf (e, "\n");
3079*56bb7041Schristos 	  if (hasblock)
3080*56bb7041Schristos 	    fprintf (e, "END\n");
3081*56bb7041Schristos 	  return;
3082*56bb7041Schristos 	}
3083*56bb7041Schristos 
3084*56bb7041Schristos       show_comment = 0;
3085*56bb7041Schristos     }
3086*56bb7041Schristos 
3087*56bb7041Schristos   if (length != 0)
3088*56bb7041Schristos 	      {
3089*56bb7041Schristos       rc_uint_type i, max_row;
3090*56bb7041Schristos       int first = 1;
3091*56bb7041Schristos 
3092*56bb7041Schristos       max_row = (show_comment ? 4 : 8);
3093*56bb7041Schristos       indent (e, 2);
3094*56bb7041Schristos       for (i = 0; i + 3 < length;)
3095*56bb7041Schristos 		  {
3096*56bb7041Schristos 	  rc_uint_type k;
3097*56bb7041Schristos 	  rc_uint_type comment_start;
3098*56bb7041Schristos 
3099*56bb7041Schristos 	  comment_start = i;
3100*56bb7041Schristos 
3101*56bb7041Schristos 	  if (! first)
3102*56bb7041Schristos 	    indent (e, 2);
3103*56bb7041Schristos 
3104*56bb7041Schristos 	  for (k = 0; k < max_row && i + 3 < length; k++, i += 4)
3105*56bb7041Schristos 		      {
3106*56bb7041Schristos 	      if (k == 0)
3107*56bb7041Schristos 		plen  = fprintf (e, "0x%lxL",
3108*56bb7041Schristos 				 (unsigned long) windres_get_32 (&wrtarget, data + i, length - i));
3109*56bb7041Schristos 			else
3110*56bb7041Schristos 		plen = fprintf (e, " 0x%lxL",
3111*56bb7041Schristos 				(unsigned long) windres_get_32 (&wrtarget, data + i, length - i)) - 1;
3112*56bb7041Schristos 	      if (has_next || (i + 4) < length)
3113*56bb7041Schristos 			  {
3114*56bb7041Schristos 		  if (plen>0 && plen < 11)
3115*56bb7041Schristos 		    indent (e, 11 - plen);
3116*56bb7041Schristos 		  fprintf (e, ",");
3117*56bb7041Schristos 			  }
3118*56bb7041Schristos 		      }
3119*56bb7041Schristos 	  if (show_comment)
3120*56bb7041Schristos 	    {
3121*56bb7041Schristos 	      fprintf (e, "\t/* ");
3122*56bb7041Schristos 	      ascii_print (e, (const char *) &data[comment_start], i - comment_start);
3123*56bb7041Schristos 	      fprintf (e, ".  */");
3124*56bb7041Schristos 		  }
3125*56bb7041Schristos 		fprintf (e, "\n");
3126*56bb7041Schristos 		first = 0;
3127*56bb7041Schristos 	      }
3128*56bb7041Schristos 
3129*56bb7041Schristos       if (i + 1 < length)
3130*56bb7041Schristos 	      {
3131*56bb7041Schristos 		if (! first)
3132*56bb7041Schristos 	    indent (e, 2);
3133*56bb7041Schristos 	  plen = fprintf (e, "0x%x",
3134*56bb7041Schristos 	  		  (int) windres_get_16 (&wrtarget, data + i, length - i));
3135*56bb7041Schristos 	  if (has_next || i + 2 < length)
3136*56bb7041Schristos 		  {
3137*56bb7041Schristos 	      if (plen > 0 && plen < 11)
3138*56bb7041Schristos 		indent (e, 11 - plen);
3139*56bb7041Schristos 	      fprintf (e, ",");
3140*56bb7041Schristos 		      }
3141*56bb7041Schristos 	  if (show_comment)
3142*56bb7041Schristos 	    {
3143*56bb7041Schristos 	      fprintf (e, "\t/* ");
3144*56bb7041Schristos 	      ascii_print (e, (const char *) &data[i], 2);
3145*56bb7041Schristos 	      fprintf (e, ".  */");
3146*56bb7041Schristos 		  }
3147*56bb7041Schristos 		fprintf (e, "\n");
3148*56bb7041Schristos 		i += 2;
3149*56bb7041Schristos 		first = 0;
3150*56bb7041Schristos 	      }
3151*56bb7041Schristos 
3152*56bb7041Schristos       if (i < length)
3153*56bb7041Schristos 	      {
3154*56bb7041Schristos 		if (! first)
3155*56bb7041Schristos 	    indent (e, 2);
3156*56bb7041Schristos 	  fprintf (e, "\"");
3157*56bb7041Schristos 	  ascii_print (e, (const char *) &data[i], 1);
3158*56bb7041Schristos 	  fprintf (e, "\"");
3159*56bb7041Schristos 	  if (has_next)
3160*56bb7041Schristos 		  fprintf (e, ",");
3161*56bb7041Schristos 		fprintf (e, "\n");
3162*56bb7041Schristos 		first = 0;
3163*56bb7041Schristos 	      }
3164*56bb7041Schristos     }
3165*56bb7041Schristos   if (hasblock)
3166*56bb7041Schristos     fprintf (e, "END\n");
3167*56bb7041Schristos }
3168*56bb7041Schristos 
3169*56bb7041Schristos /* Write out an rcdata resource.  This is also used for other types of
3170*56bb7041Schristos    resources that need to print arbitrary data.  */
3171*56bb7041Schristos 
3172*56bb7041Schristos static void
write_rc_rcdata(FILE * e,const rc_rcdata_item * rcdata,int ind)3173*56bb7041Schristos write_rc_rcdata (FILE *e, const rc_rcdata_item *rcdata, int ind)
3174*56bb7041Schristos {
3175*56bb7041Schristos   const rc_rcdata_item *ri;
3176*56bb7041Schristos 
3177*56bb7041Schristos   indent (e, ind);
3178*56bb7041Schristos   fprintf (e, "BEGIN\n");
3179*56bb7041Schristos 
3180*56bb7041Schristos   for (ri = rcdata; ri != NULL; ri = ri->next)
3181*56bb7041Schristos     {
3182*56bb7041Schristos       if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0)
3183*56bb7041Schristos 	continue;
3184*56bb7041Schristos 
3185*56bb7041Schristos       switch (ri->type)
3186*56bb7041Schristos 	{
3187*56bb7041Schristos 	default:
3188*56bb7041Schristos 	  abort ();
3189*56bb7041Schristos 
3190*56bb7041Schristos 	case RCDATA_WORD:
3191*56bb7041Schristos 	  indent (e, ind + 2);
3192*56bb7041Schristos 	  fprintf (e, "%ld", (long) (ri->u.word & 0xffff));
3193*56bb7041Schristos 	  break;
3194*56bb7041Schristos 
3195*56bb7041Schristos 	case RCDATA_DWORD:
3196*56bb7041Schristos 	  indent (e, ind + 2);
3197*56bb7041Schristos 	  fprintf (e, "%luL", (unsigned long) ri->u.dword);
3198*56bb7041Schristos 	  break;
3199*56bb7041Schristos 
3200*56bb7041Schristos 	case RCDATA_STRING:
3201*56bb7041Schristos 	  indent (e, ind + 2);
3202*56bb7041Schristos 	  fprintf (e, "\"");
3203*56bb7041Schristos 	  ascii_print (e, ri->u.string.s, ri->u.string.length);
3204*56bb7041Schristos 	  fprintf (e, "\"");
3205*56bb7041Schristos 	  break;
3206*56bb7041Schristos 
3207*56bb7041Schristos 	case RCDATA_WSTRING:
3208*56bb7041Schristos 	  indent (e, ind + 2);
3209*56bb7041Schristos 	  fprintf (e, "L\"");
3210*56bb7041Schristos 	  unicode_print (e, ri->u.wstring.w, ri->u.wstring.length);
3211*56bb7041Schristos 	  fprintf (e, "\"");
3212*56bb7041Schristos 	  break;
3213*56bb7041Schristos 
3214*56bb7041Schristos 	case RCDATA_BUFFER:
3215*56bb7041Schristos 	  write_rc_datablock (e, (rc_uint_type) ri->u.buffer.length,
3216*56bb7041Schristos 	  		      (const bfd_byte *) ri->u.buffer.data,
3217*56bb7041Schristos 	    		      ri->next != NULL, 0, -1);
3218*56bb7041Schristos 	    break;
3219*56bb7041Schristos 	}
3220*56bb7041Schristos 
3221*56bb7041Schristos       if (ri->type != RCDATA_BUFFER)
3222*56bb7041Schristos 	{
3223*56bb7041Schristos 	  if (ri->next != NULL)
3224*56bb7041Schristos 	    fprintf (e, ",");
3225*56bb7041Schristos 	  fprintf (e, "\n");
3226*56bb7041Schristos 	}
3227*56bb7041Schristos     }
3228*56bb7041Schristos 
3229*56bb7041Schristos   indent (e, ind);
3230*56bb7041Schristos   fprintf (e, "END\n");
3231*56bb7041Schristos }
3232*56bb7041Schristos 
3233*56bb7041Schristos /* Write out a stringtable resource.  */
3234*56bb7041Schristos 
3235*56bb7041Schristos static void
write_rc_stringtable(FILE * e,const rc_res_id * name,const rc_stringtable * stringtable)3236*56bb7041Schristos write_rc_stringtable (FILE *e, const rc_res_id *name,
3237*56bb7041Schristos 		      const rc_stringtable *stringtable)
3238*56bb7041Schristos {
3239*56bb7041Schristos   rc_uint_type offset;
3240*56bb7041Schristos   int i;
3241*56bb7041Schristos 
3242*56bb7041Schristos   if (name != NULL && ! name->named)
3243*56bb7041Schristos     offset = (name->u.id - 1) << 4;
3244*56bb7041Schristos   else
3245*56bb7041Schristos     {
3246*56bb7041Schristos       fprintf (e, "/* %s string table name.  */\n",
3247*56bb7041Schristos 	       name == NULL ? "Missing" : "Invalid");
3248*56bb7041Schristos       offset = 0;
3249*56bb7041Schristos     }
3250*56bb7041Schristos 
3251*56bb7041Schristos   fprintf (e, "BEGIN\n");
3252*56bb7041Schristos 
3253*56bb7041Schristos   for (i = 0; i < 16; i++)
3254*56bb7041Schristos     {
3255*56bb7041Schristos       if (stringtable->strings[i].length != 0)
3256*56bb7041Schristos 	{
3257*56bb7041Schristos 	  fprintf (e, "  %lu, ", (unsigned long) offset + i);
3258*56bb7041Schristos 	  unicode_print_quoted (e, stringtable->strings[i].string,
3259*56bb7041Schristos 			 stringtable->strings[i].length);
3260*56bb7041Schristos 	  fprintf (e, "\n");
3261*56bb7041Schristos 	}
3262*56bb7041Schristos     }
3263*56bb7041Schristos 
3264*56bb7041Schristos   fprintf (e, "END\n");
3265*56bb7041Schristos }
3266*56bb7041Schristos 
3267*56bb7041Schristos /* Write out a versioninfo resource.  */
3268*56bb7041Schristos 
3269*56bb7041Schristos static void
write_rc_versioninfo(FILE * e,const rc_versioninfo * versioninfo)3270*56bb7041Schristos write_rc_versioninfo (FILE *e, const rc_versioninfo *versioninfo)
3271*56bb7041Schristos {
3272*56bb7041Schristos   const rc_fixed_versioninfo *f;
3273*56bb7041Schristos   const rc_ver_info *vi;
3274*56bb7041Schristos 
3275*56bb7041Schristos   f = versioninfo->fixed;
3276*56bb7041Schristos   if (f->file_version_ms != 0 || f->file_version_ls != 0)
3277*56bb7041Schristos     fprintf (e, " FILEVERSION %u, %u, %u, %u\n",
3278*56bb7041Schristos 	     (unsigned int) ((f->file_version_ms >> 16) & 0xffff),
3279*56bb7041Schristos 	     (unsigned int) (f->file_version_ms & 0xffff),
3280*56bb7041Schristos 	     (unsigned int) ((f->file_version_ls >> 16) & 0xffff),
3281*56bb7041Schristos 	     (unsigned int) (f->file_version_ls & 0xffff));
3282*56bb7041Schristos   if (f->product_version_ms != 0 || f->product_version_ls != 0)
3283*56bb7041Schristos     fprintf (e, " PRODUCTVERSION %u, %u, %u, %u\n",
3284*56bb7041Schristos 	     (unsigned int) ((f->product_version_ms >> 16) & 0xffff),
3285*56bb7041Schristos 	     (unsigned int) (f->product_version_ms & 0xffff),
3286*56bb7041Schristos 	     (unsigned int) ((f->product_version_ls >> 16) & 0xffff),
3287*56bb7041Schristos 	     (unsigned int) (f->product_version_ls & 0xffff));
3288*56bb7041Schristos   if (f->file_flags_mask != 0)
3289*56bb7041Schristos     fprintf (e, " FILEFLAGSMASK 0x%x\n", (unsigned int) f->file_flags_mask);
3290*56bb7041Schristos   if (f->file_flags != 0)
3291*56bb7041Schristos     fprintf (e, " FILEFLAGS 0x%x\n", (unsigned int) f->file_flags);
3292*56bb7041Schristos   if (f->file_os != 0)
3293*56bb7041Schristos     fprintf (e, " FILEOS 0x%x\n", (unsigned int) f->file_os);
3294*56bb7041Schristos   if (f->file_type != 0)
3295*56bb7041Schristos     fprintf (e, " FILETYPE 0x%x\n", (unsigned int) f->file_type);
3296*56bb7041Schristos   if (f->file_subtype != 0)
3297*56bb7041Schristos     fprintf (e, " FILESUBTYPE 0x%x\n", (unsigned int) f->file_subtype);
3298*56bb7041Schristos   if (f->file_date_ms != 0 || f->file_date_ls != 0)
3299*56bb7041Schristos     fprintf (e, "/* Date: %u, %u.  */\n",
3300*56bb7041Schristos     	     (unsigned int) f->file_date_ms, (unsigned int) f->file_date_ls);
3301*56bb7041Schristos 
3302*56bb7041Schristos   fprintf (e, "BEGIN\n");
3303*56bb7041Schristos 
3304*56bb7041Schristos   for (vi = versioninfo->var; vi != NULL; vi = vi->next)
3305*56bb7041Schristos     {
3306*56bb7041Schristos       switch (vi->type)
3307*56bb7041Schristos 	{
3308*56bb7041Schristos 	case VERINFO_STRING:
3309*56bb7041Schristos 	  {
3310*56bb7041Schristos 	    const rc_ver_stringtable *vst;
3311*56bb7041Schristos 	    const rc_ver_stringinfo *vs;
3312*56bb7041Schristos 
3313*56bb7041Schristos 	    fprintf (e, "  BLOCK \"StringFileInfo\"\n");
3314*56bb7041Schristos 	    fprintf (e, "  BEGIN\n");
3315*56bb7041Schristos 
3316*56bb7041Schristos 	    for (vst = vi->u.string.stringtables; vst != NULL; vst = vst->next)
3317*56bb7041Schristos 	      {
3318*56bb7041Schristos 		fprintf (e, "    BLOCK ");
3319*56bb7041Schristos 		unicode_print_quoted (e, vst->language, -1);
3320*56bb7041Schristos 
3321*56bb7041Schristos 		fprintf (e, "\n");
3322*56bb7041Schristos 		fprintf (e, "    BEGIN\n");
3323*56bb7041Schristos 
3324*56bb7041Schristos 		for (vs = vst->strings; vs != NULL; vs = vs->next)
3325*56bb7041Schristos 		  {
3326*56bb7041Schristos 		    fprintf (e, "      VALUE ");
3327*56bb7041Schristos 		    unicode_print_quoted (e, vs->key, -1);
3328*56bb7041Schristos 		    fprintf (e, ", ");
3329*56bb7041Schristos 		    unicode_print_quoted (e, vs->value, -1);
3330*56bb7041Schristos 		    fprintf (e, "\n");
3331*56bb7041Schristos 		  }
3332*56bb7041Schristos 
3333*56bb7041Schristos 		fprintf (e, "    END\n");
3334*56bb7041Schristos 	      }
3335*56bb7041Schristos 	    fprintf (e, "  END\n");
3336*56bb7041Schristos 	    break;
3337*56bb7041Schristos 	  }
3338*56bb7041Schristos 
3339*56bb7041Schristos 	case VERINFO_VAR:
3340*56bb7041Schristos 	  {
3341*56bb7041Schristos 	    const rc_ver_varinfo *vv;
3342*56bb7041Schristos 
3343*56bb7041Schristos 	    fprintf (e, "  BLOCK \"VarFileInfo\"\n");
3344*56bb7041Schristos 	    fprintf (e, "  BEGIN\n");
3345*56bb7041Schristos 	    fprintf (e, "    VALUE ");
3346*56bb7041Schristos 	    unicode_print_quoted (e, vi->u.var.key, -1);
3347*56bb7041Schristos 
3348*56bb7041Schristos 	    for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
3349*56bb7041Schristos 	      fprintf (e, ", 0x%x, %d", (unsigned int) vv->language,
3350*56bb7041Schristos 		       (int) vv->charset);
3351*56bb7041Schristos 
3352*56bb7041Schristos 	    fprintf (e, "\n  END\n");
3353*56bb7041Schristos 
3354*56bb7041Schristos 	    break;
3355*56bb7041Schristos 	  }
3356*56bb7041Schristos 	}
3357*56bb7041Schristos     }
3358*56bb7041Schristos 
3359*56bb7041Schristos   fprintf (e, "END\n");
3360*56bb7041Schristos }
3361*56bb7041Schristos 
3362*56bb7041Schristos static rc_uint_type
rcdata_copy(const rc_rcdata_item * src,bfd_byte * dst)3363*56bb7041Schristos rcdata_copy (const rc_rcdata_item *src, bfd_byte *dst)
3364*56bb7041Schristos {
3365*56bb7041Schristos   if (! src)
3366*56bb7041Schristos     return 0;
3367*56bb7041Schristos   switch (src->type)
3368*56bb7041Schristos 	{
3369*56bb7041Schristos     case RCDATA_WORD:
3370*56bb7041Schristos       if (dst)
3371*56bb7041Schristos 	windres_put_16 (&wrtarget, dst, (rc_uint_type) src->u.word);
3372*56bb7041Schristos       return 2;
3373*56bb7041Schristos     case RCDATA_DWORD:
3374*56bb7041Schristos       if (dst)
3375*56bb7041Schristos 	windres_put_32 (&wrtarget, dst, (rc_uint_type) src->u.dword);
3376*56bb7041Schristos       return 4;
3377*56bb7041Schristos     case RCDATA_STRING:
3378*56bb7041Schristos       if (dst && src->u.string.length)
3379*56bb7041Schristos 	memcpy (dst, src->u.string.s, src->u.string.length);
3380*56bb7041Schristos       return (rc_uint_type) src->u.string.length;
3381*56bb7041Schristos     case RCDATA_WSTRING:
3382*56bb7041Schristos       if (dst && src->u.wstring.length)
3383*56bb7041Schristos 	memcpy (dst, src->u.wstring.w, src->u.wstring.length * sizeof (unichar));
3384*56bb7041Schristos       return (rc_uint_type) (src->u.wstring.length  * sizeof (unichar));
3385*56bb7041Schristos     case RCDATA_BUFFER:
3386*56bb7041Schristos       if (dst && src->u.buffer.length)
3387*56bb7041Schristos 	memcpy (dst, src->u.buffer.data, src->u.buffer.length);
3388*56bb7041Schristos       return (rc_uint_type) src->u.buffer.length;
3389*56bb7041Schristos     default:
3390*56bb7041Schristos       abort ();
3391*56bb7041Schristos     }
3392*56bb7041Schristos   /* Never reached.  */
3393*56bb7041Schristos   return 0;
3394*56bb7041Schristos }
3395