xref: /openbsd-src/gnu/usr.bin/binutils-2.17/binutils/resrc.c (revision d2386abe6d72afba906e28bc7357d44f31adee3f)
13d8817e4Smiod /* resrc.c -- read and write Windows rc files.
23d8817e4Smiod    Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005
33d8817e4Smiod    Free Software Foundation, Inc.
43d8817e4Smiod    Written by Ian Lance Taylor, Cygnus Support.
53d8817e4Smiod 
63d8817e4Smiod    This file is part of GNU Binutils.
73d8817e4Smiod 
83d8817e4Smiod    This program is free software; you can redistribute it and/or modify
93d8817e4Smiod    it under the terms of the GNU General Public License as published by
103d8817e4Smiod    the Free Software Foundation; either version 2 of the License, or
113d8817e4Smiod    (at your option) any later version.
123d8817e4Smiod 
133d8817e4Smiod    This program is distributed in the hope that it will be useful,
143d8817e4Smiod    but WITHOUT ANY WARRANTY; without even the implied warranty of
153d8817e4Smiod    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
163d8817e4Smiod    GNU General Public License for more details.
173d8817e4Smiod 
183d8817e4Smiod    You should have received a copy of the GNU General Public License
193d8817e4Smiod    along with this program; if not, write to the Free Software
203d8817e4Smiod    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
213d8817e4Smiod    02110-1301, USA.  */
223d8817e4Smiod 
233d8817e4Smiod /* This file contains functions that read and write Windows rc files.
243d8817e4Smiod    These are text files that represent resources.  */
253d8817e4Smiod 
263d8817e4Smiod #include "bfd.h"
273d8817e4Smiod #include "bucomm.h"
283d8817e4Smiod #include "libiberty.h"
293d8817e4Smiod #include "safe-ctype.h"
303d8817e4Smiod #include "windres.h"
313d8817e4Smiod 
323d8817e4Smiod #include <assert.h>
333d8817e4Smiod #include <errno.h>
343d8817e4Smiod #include <sys/stat.h>
353d8817e4Smiod #ifdef HAVE_UNISTD_H
363d8817e4Smiod #include <unistd.h>
373d8817e4Smiod #endif
383d8817e4Smiod 
393d8817e4Smiod #ifdef HAVE_SYS_WAIT_H
403d8817e4Smiod #include <sys/wait.h>
413d8817e4Smiod #else /* ! HAVE_SYS_WAIT_H */
423d8817e4Smiod #if ! defined (_WIN32) || defined (__CYGWIN__)
433d8817e4Smiod #ifndef WIFEXITED
443d8817e4Smiod #define WIFEXITED(w)	(((w)&0377) == 0)
453d8817e4Smiod #endif
463d8817e4Smiod #ifndef WIFSIGNALED
473d8817e4Smiod #define WIFSIGNALED(w)	(((w)&0377) != 0177 && ((w)&~0377) == 0)
483d8817e4Smiod #endif
493d8817e4Smiod #ifndef WTERMSIG
503d8817e4Smiod #define WTERMSIG(w)	((w) & 0177)
513d8817e4Smiod #endif
523d8817e4Smiod #ifndef WEXITSTATUS
533d8817e4Smiod #define WEXITSTATUS(w)	(((w) >> 8) & 0377)
543d8817e4Smiod #endif
553d8817e4Smiod #else /* defined (_WIN32) && ! defined (__CYGWIN__) */
563d8817e4Smiod #ifndef WIFEXITED
573d8817e4Smiod #define WIFEXITED(w)	(((w) & 0xff) == 0)
583d8817e4Smiod #endif
593d8817e4Smiod #ifndef WIFSIGNALED
603d8817e4Smiod #define WIFSIGNALED(w)	(((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
613d8817e4Smiod #endif
623d8817e4Smiod #ifndef WTERMSIG
633d8817e4Smiod #define WTERMSIG(w)	((w) & 0x7f)
643d8817e4Smiod #endif
653d8817e4Smiod #ifndef WEXITSTATUS
663d8817e4Smiod #define WEXITSTATUS(w)	(((w) & 0xff00) >> 8)
673d8817e4Smiod #endif
683d8817e4Smiod #endif /* defined (_WIN32) && ! defined (__CYGWIN__) */
693d8817e4Smiod #endif /* ! HAVE_SYS_WAIT_H */
703d8817e4Smiod 
713d8817e4Smiod #ifndef STDOUT_FILENO
723d8817e4Smiod #define STDOUT_FILENO 1
733d8817e4Smiod #endif
743d8817e4Smiod 
753d8817e4Smiod #if defined (_WIN32) && ! defined (__CYGWIN__)
763d8817e4Smiod #define popen _popen
773d8817e4Smiod #define pclose _pclose
783d8817e4Smiod #endif
793d8817e4Smiod 
803d8817e4Smiod /* The default preprocessor.  */
813d8817e4Smiod 
823d8817e4Smiod #define DEFAULT_PREPROCESSOR "gcc -E -xc -DRC_INVOKED"
833d8817e4Smiod 
843d8817e4Smiod /* We read the directory entries in a cursor or icon file into
853d8817e4Smiod    instances of this structure.  */
863d8817e4Smiod 
873d8817e4Smiod struct icondir
883d8817e4Smiod {
893d8817e4Smiod   /* Width of image.  */
903d8817e4Smiod   unsigned char width;
913d8817e4Smiod   /* Height of image.  */
923d8817e4Smiod   unsigned char height;
933d8817e4Smiod   /* Number of colors in image.  */
943d8817e4Smiod   unsigned char colorcount;
953d8817e4Smiod   union
963d8817e4Smiod   {
973d8817e4Smiod     struct
983d8817e4Smiod     {
993d8817e4Smiod       /* Color planes.  */
1003d8817e4Smiod       unsigned short planes;
1013d8817e4Smiod       /* Bits per pixel.  */
1023d8817e4Smiod       unsigned short bits;
1033d8817e4Smiod     } icon;
1043d8817e4Smiod     struct
1053d8817e4Smiod     {
1063d8817e4Smiod       /* X coordinate of hotspot.  */
1073d8817e4Smiod       unsigned short xhotspot;
1083d8817e4Smiod       /* Y coordinate of hotspot.  */
1093d8817e4Smiod       unsigned short yhotspot;
1103d8817e4Smiod     } cursor;
1113d8817e4Smiod   } u;
1123d8817e4Smiod   /* Bytes in image.  */
1133d8817e4Smiod   unsigned long bytes;
1143d8817e4Smiod   /* File offset of image.  */
1153d8817e4Smiod   unsigned long offset;
1163d8817e4Smiod };
1173d8817e4Smiod 
1183d8817e4Smiod /* The name of the rc file we are reading.  */
1193d8817e4Smiod 
1203d8817e4Smiod char *rc_filename;
1213d8817e4Smiod 
1223d8817e4Smiod /* The line number in the rc file.  */
1233d8817e4Smiod 
1243d8817e4Smiod int rc_lineno;
1253d8817e4Smiod 
1263d8817e4Smiod /* The pipe we are reading from, so that we can close it if we exit.  */
1273d8817e4Smiod 
1283d8817e4Smiod static FILE *cpp_pipe;
1293d8817e4Smiod 
1303d8817e4Smiod /* The temporary file used if we're not using popen, so we can delete it
1313d8817e4Smiod    if we exit.  */
1323d8817e4Smiod 
1333d8817e4Smiod static char *cpp_temp_file;
1343d8817e4Smiod 
1353d8817e4Smiod /* Input stream is either a file or a pipe.  */
1363d8817e4Smiod 
1373d8817e4Smiod static enum {ISTREAM_PIPE, ISTREAM_FILE} istream_type;
1383d8817e4Smiod 
1393d8817e4Smiod /* As we read the rc file, we attach information to this structure.  */
1403d8817e4Smiod 
1413d8817e4Smiod static struct res_directory *resources;
1423d8817e4Smiod 
1433d8817e4Smiod /* The number of cursor resources we have written out.  */
1443d8817e4Smiod 
1453d8817e4Smiod static int cursors;
1463d8817e4Smiod 
1473d8817e4Smiod /* The number of font resources we have written out.  */
1483d8817e4Smiod 
1493d8817e4Smiod static int fonts;
1503d8817e4Smiod 
1513d8817e4Smiod /* Font directory information.  */
1523d8817e4Smiod 
1533d8817e4Smiod struct fontdir *fontdirs;
1543d8817e4Smiod 
1553d8817e4Smiod /* Resource info to use for fontdirs.  */
1563d8817e4Smiod 
1573d8817e4Smiod struct res_res_info fontdirs_resinfo;
1583d8817e4Smiod 
1593d8817e4Smiod /* The number of icon resources we have written out.  */
1603d8817e4Smiod 
1613d8817e4Smiod static int icons;
1623d8817e4Smiod 
1633d8817e4Smiod /* Local functions.  */
1643d8817e4Smiod 
1653d8817e4Smiod static int run_cmd (char *, const char *);
1663d8817e4Smiod static FILE *open_input_stream (char *);
1673d8817e4Smiod static FILE *look_for_default
1683d8817e4Smiod   (char *, const char *, int, const char *, const char *);
1693d8817e4Smiod static void close_input_stream (void);
1703d8817e4Smiod static void unexpected_eof (const char *);
1713d8817e4Smiod static int get_word (FILE *, const char *);
1723d8817e4Smiod static unsigned long get_long (FILE *, const char *);
1733d8817e4Smiod static void get_data (FILE *, unsigned char *, unsigned long, const char *);
1743d8817e4Smiod static void define_fontdirs (void);
1753d8817e4Smiod 
1763d8817e4Smiod /* Run `cmd' and redirect the output to `redir'.  */
1773d8817e4Smiod 
1783d8817e4Smiod static int
run_cmd(char * cmd,const char * redir)1793d8817e4Smiod run_cmd (char *cmd, const char *redir)
1803d8817e4Smiod {
1813d8817e4Smiod   char *s;
1823d8817e4Smiod   int pid, wait_status, retcode;
1833d8817e4Smiod   int i;
1843d8817e4Smiod   const char **argv;
1853d8817e4Smiod   char *errmsg_fmt, *errmsg_arg;
186*d2386abeSmiod #if defined(__MSDOS__) && !defined(__GO32__)
1873d8817e4Smiod   char *temp_base = choose_temp_base ();
188*d2386abeSmiod #else
189*d2386abeSmiod   char *temp_base = NULL;
190*d2386abeSmiod #endif
1913d8817e4Smiod   int in_quote;
1923d8817e4Smiod   char sep;
1933d8817e4Smiod   int redir_handle = -1;
1943d8817e4Smiod   int stdout_save = -1;
1953d8817e4Smiod 
1963d8817e4Smiod   /* Count the args.  */
1973d8817e4Smiod   i = 0;
1983d8817e4Smiod 
1993d8817e4Smiod   for (s = cmd; *s; s++)
2003d8817e4Smiod     if (*s == ' ')
2013d8817e4Smiod       i++;
2023d8817e4Smiod 
2033d8817e4Smiod   i++;
2043d8817e4Smiod   argv = alloca (sizeof (char *) * (i + 3));
2053d8817e4Smiod   i = 0;
2063d8817e4Smiod   s = cmd;
2073d8817e4Smiod 
2083d8817e4Smiod   while (1)
2093d8817e4Smiod     {
2103d8817e4Smiod       while (*s == ' ' && *s != 0)
2113d8817e4Smiod 	s++;
2123d8817e4Smiod 
2133d8817e4Smiod       if (*s == 0)
2143d8817e4Smiod 	break;
2153d8817e4Smiod 
2163d8817e4Smiod       in_quote = (*s == '\'' || *s == '"');
2173d8817e4Smiod       sep = (in_quote) ? *s++ : ' ';
2183d8817e4Smiod       argv[i++] = s;
2193d8817e4Smiod 
2203d8817e4Smiod       while (*s != sep && *s != 0)
2213d8817e4Smiod 	s++;
2223d8817e4Smiod 
2233d8817e4Smiod       if (*s == 0)
2243d8817e4Smiod 	break;
2253d8817e4Smiod 
2263d8817e4Smiod       *s++ = 0;
2273d8817e4Smiod 
2283d8817e4Smiod       if (in_quote)
2293d8817e4Smiod 	s++;
2303d8817e4Smiod     }
2313d8817e4Smiod   argv[i++] = NULL;
2323d8817e4Smiod 
2333d8817e4Smiod   /* Setup the redirection.  We can't use the usual fork/exec and redirect
2343d8817e4Smiod      since we may be running on non-POSIX Windows host.  */
2353d8817e4Smiod 
2363d8817e4Smiod   fflush (stdout);
2373d8817e4Smiod   fflush (stderr);
2383d8817e4Smiod 
2393d8817e4Smiod   /* Open temporary output file.  */
2403d8817e4Smiod   redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT, 0666);
2413d8817e4Smiod   if (redir_handle == -1)
2423d8817e4Smiod     fatal (_("can't open temporary file `%s': %s"), redir,
2433d8817e4Smiod 	   strerror (errno));
2443d8817e4Smiod 
2453d8817e4Smiod   /* Duplicate the stdout file handle so it can be restored later.  */
2463d8817e4Smiod   stdout_save = dup (STDOUT_FILENO);
2473d8817e4Smiod   if (stdout_save == -1)
2483d8817e4Smiod     fatal (_("can't redirect stdout: `%s': %s"), redir, strerror (errno));
2493d8817e4Smiod 
2503d8817e4Smiod   /* Redirect stdout to our output file.  */
2513d8817e4Smiod   dup2 (redir_handle, STDOUT_FILENO);
2523d8817e4Smiod 
2533d8817e4Smiod   pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
2543d8817e4Smiod 		  &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
2553d8817e4Smiod 
2563d8817e4Smiod   /* Restore stdout to its previous setting.  */
2573d8817e4Smiod   dup2 (stdout_save, STDOUT_FILENO);
2583d8817e4Smiod 
2593d8817e4Smiod   /* Close response file.  */
2603d8817e4Smiod   close (redir_handle);
2613d8817e4Smiod 
2623d8817e4Smiod   if (pid == -1)
2633d8817e4Smiod     {
2643d8817e4Smiod       fatal (_("%s %s: %s"), errmsg_fmt, errmsg_arg, strerror (errno));
2653d8817e4Smiod       return 1;
2663d8817e4Smiod     }
2673d8817e4Smiod 
2683d8817e4Smiod   retcode = 0;
2693d8817e4Smiod   pid = pwait (pid, &wait_status, 0);
2703d8817e4Smiod 
2713d8817e4Smiod   if (pid == -1)
2723d8817e4Smiod     {
2733d8817e4Smiod       fatal (_("wait: %s"), strerror (errno));
2743d8817e4Smiod       retcode = 1;
2753d8817e4Smiod     }
2763d8817e4Smiod   else if (WIFSIGNALED (wait_status))
2773d8817e4Smiod     {
2783d8817e4Smiod       fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
2793d8817e4Smiod       retcode = 1;
2803d8817e4Smiod     }
2813d8817e4Smiod   else if (WIFEXITED (wait_status))
2823d8817e4Smiod     {
2833d8817e4Smiod       if (WEXITSTATUS (wait_status) != 0)
2843d8817e4Smiod 	{
2853d8817e4Smiod 	  fatal (_("%s exited with status %d"), cmd,
2863d8817e4Smiod 	         WEXITSTATUS (wait_status));
2873d8817e4Smiod 	  retcode = 1;
2883d8817e4Smiod 	}
2893d8817e4Smiod     }
2903d8817e4Smiod   else
2913d8817e4Smiod     retcode = 1;
2923d8817e4Smiod 
2933d8817e4Smiod   return retcode;
2943d8817e4Smiod }
2953d8817e4Smiod 
2963d8817e4Smiod static FILE *
open_input_stream(char * cmd)2973d8817e4Smiod open_input_stream (char *cmd)
2983d8817e4Smiod {
2993d8817e4Smiod   if (istream_type == ISTREAM_FILE)
3003d8817e4Smiod     {
301*d2386abeSmiod       cpp_temp_file = make_temp_file (".irc");
3023d8817e4Smiod 
3033d8817e4Smiod       if (run_cmd (cmd, cpp_temp_file))
3043d8817e4Smiod 	fatal (_("can't execute `%s': %s"), cmd, strerror (errno));
3053d8817e4Smiod 
3063d8817e4Smiod       cpp_pipe = fopen (cpp_temp_file, FOPEN_RT);;
3073d8817e4Smiod       if (cpp_pipe == NULL)
3083d8817e4Smiod 	fatal (_("can't open temporary file `%s': %s"),
3093d8817e4Smiod 	       cpp_temp_file, strerror (errno));
3103d8817e4Smiod 
3113d8817e4Smiod       if (verbose)
3123d8817e4Smiod 	fprintf (stderr,
3133d8817e4Smiod 	         _("Using temporary file `%s' to read preprocessor output\n"),
3143d8817e4Smiod 		 cpp_temp_file);
3153d8817e4Smiod     }
3163d8817e4Smiod   else
3173d8817e4Smiod     {
3183d8817e4Smiod       cpp_pipe = popen (cmd, FOPEN_RT);
3193d8817e4Smiod       if (cpp_pipe == NULL)
3203d8817e4Smiod 	fatal (_("can't popen `%s': %s"), cmd, strerror (errno));
3213d8817e4Smiod       if (verbose)
3223d8817e4Smiod 	fprintf (stderr, _("Using popen to read preprocessor output\n"));
3233d8817e4Smiod     }
3243d8817e4Smiod 
3253d8817e4Smiod   xatexit (close_input_stream);
3263d8817e4Smiod   return cpp_pipe;
3273d8817e4Smiod }
3283d8817e4Smiod 
3293d8817e4Smiod /* look for the preprocessor program */
3303d8817e4Smiod 
3313d8817e4Smiod static FILE *
look_for_default(char * cmd,const char * prefix,int end_prefix,const char * preprocargs,const char * filename)3323d8817e4Smiod look_for_default (char *cmd, const char *prefix, int end_prefix,
3333d8817e4Smiod 		  const char *preprocargs, const char *filename)
3343d8817e4Smiod {
3353d8817e4Smiod   char *space;
3363d8817e4Smiod   int found;
3373d8817e4Smiod   struct stat s;
3383d8817e4Smiod 
3393d8817e4Smiod   strcpy (cmd, prefix);
3403d8817e4Smiod 
3413d8817e4Smiod   sprintf (cmd + end_prefix, "%s", DEFAULT_PREPROCESSOR);
3423d8817e4Smiod   space = strchr (cmd + end_prefix, ' ');
3433d8817e4Smiod   if (space)
3443d8817e4Smiod     *space = 0;
3453d8817e4Smiod 
3463d8817e4Smiod   if (
3473d8817e4Smiod #if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32)
3483d8817e4Smiod       strchr (cmd, '\\') ||
3493d8817e4Smiod #endif
3503d8817e4Smiod       strchr (cmd, '/'))
3513d8817e4Smiod     {
3523d8817e4Smiod       found = (stat (cmd, &s) == 0
3533d8817e4Smiod #ifdef HAVE_EXECUTABLE_SUFFIX
3543d8817e4Smiod 	       || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
3553d8817e4Smiod #endif
3563d8817e4Smiod 	       );
3573d8817e4Smiod 
3583d8817e4Smiod       if (! found)
3593d8817e4Smiod 	{
3603d8817e4Smiod 	  if (verbose)
3613d8817e4Smiod 	    fprintf (stderr, _("Tried `%s'\n"), cmd);
3623d8817e4Smiod 	  return NULL;
3633d8817e4Smiod 	}
3643d8817e4Smiod     }
3653d8817e4Smiod 
3663d8817e4Smiod   strcpy (cmd, prefix);
3673d8817e4Smiod 
3683d8817e4Smiod   sprintf (cmd + end_prefix, "%s %s %s",
3693d8817e4Smiod 	   DEFAULT_PREPROCESSOR, preprocargs, filename);
3703d8817e4Smiod 
3713d8817e4Smiod   if (verbose)
3723d8817e4Smiod     fprintf (stderr, _("Using `%s'\n"), cmd);
3733d8817e4Smiod 
3743d8817e4Smiod   cpp_pipe = open_input_stream (cmd);
3753d8817e4Smiod   return cpp_pipe;
3763d8817e4Smiod }
3773d8817e4Smiod 
3783d8817e4Smiod /* Read an rc file.  */
3793d8817e4Smiod 
3803d8817e4Smiod struct res_directory *
read_rc_file(const char * filename,const char * preprocessor,const char * preprocargs,int language,int use_temp_file)3813d8817e4Smiod read_rc_file (const char *filename, const char *preprocessor,
3823d8817e4Smiod 	      const char *preprocargs, int language, int use_temp_file)
3833d8817e4Smiod {
3843d8817e4Smiod   char *cmd;
3853d8817e4Smiod 
3863d8817e4Smiod   istream_type = (use_temp_file) ? ISTREAM_FILE : ISTREAM_PIPE;
3873d8817e4Smiod 
3883d8817e4Smiod   if (preprocargs == NULL)
3893d8817e4Smiod     preprocargs = "";
3903d8817e4Smiod   if (filename == NULL)
3913d8817e4Smiod     filename = "-";
3923d8817e4Smiod 
3933d8817e4Smiod   if (preprocessor)
3943d8817e4Smiod     {
3953d8817e4Smiod       cmd = xmalloc (strlen (preprocessor)
3963d8817e4Smiod 		     + strlen (preprocargs)
3973d8817e4Smiod 		     + strlen (filename)
3983d8817e4Smiod 		     + 10);
3993d8817e4Smiod       sprintf (cmd, "%s %s %s", preprocessor, preprocargs, filename);
4003d8817e4Smiod 
4013d8817e4Smiod       cpp_pipe = open_input_stream (cmd);
4023d8817e4Smiod     }
4033d8817e4Smiod   else
4043d8817e4Smiod     {
4053d8817e4Smiod       char *dash, *slash, *cp;
4063d8817e4Smiod 
4073d8817e4Smiod       preprocessor = DEFAULT_PREPROCESSOR;
4083d8817e4Smiod 
4093d8817e4Smiod       cmd = xmalloc (strlen (program_name)
4103d8817e4Smiod 		     + strlen (preprocessor)
4113d8817e4Smiod 		     + strlen (preprocargs)
4123d8817e4Smiod 		     + strlen (filename)
4133d8817e4Smiod #ifdef HAVE_EXECUTABLE_SUFFIX
4143d8817e4Smiod 		     + strlen (EXECUTABLE_SUFFIX)
4153d8817e4Smiod #endif
4163d8817e4Smiod 		     + 10);
4173d8817e4Smiod 
4183d8817e4Smiod 
4193d8817e4Smiod       dash = slash = 0;
4203d8817e4Smiod       for (cp = program_name; *cp; cp++)
4213d8817e4Smiod 	{
4223d8817e4Smiod 	  if (*cp == '-')
4233d8817e4Smiod 	    dash = cp;
4243d8817e4Smiod 	  if (
4253d8817e4Smiod #if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32)
4263d8817e4Smiod 	      *cp == ':' || *cp == '\\' ||
4273d8817e4Smiod #endif
4283d8817e4Smiod 	      *cp == '/')
4293d8817e4Smiod 	    {
4303d8817e4Smiod 	      slash = cp;
4313d8817e4Smiod 	      dash = 0;
4323d8817e4Smiod 	    }
4333d8817e4Smiod 	}
4343d8817e4Smiod 
4353d8817e4Smiod       cpp_pipe = 0;
4363d8817e4Smiod 
4373d8817e4Smiod       if (dash)
4383d8817e4Smiod 	{
4393d8817e4Smiod 	  /* First, try looking for a prefixed gcc in the windres
4403d8817e4Smiod 	     directory, with the same prefix as windres */
4413d8817e4Smiod 
4423d8817e4Smiod 	  cpp_pipe = look_for_default (cmd, program_name, dash-program_name+1,
4433d8817e4Smiod 				       preprocargs, filename);
4443d8817e4Smiod 	}
4453d8817e4Smiod 
4463d8817e4Smiod       if (slash && !cpp_pipe)
4473d8817e4Smiod 	{
4483d8817e4Smiod 	  /* Next, try looking for a gcc in the same directory as
4493d8817e4Smiod              that windres */
4503d8817e4Smiod 
4513d8817e4Smiod 	  cpp_pipe = look_for_default (cmd, program_name, slash-program_name+1,
4523d8817e4Smiod 				       preprocargs, filename);
4533d8817e4Smiod 	}
4543d8817e4Smiod 
4553d8817e4Smiod       if (!cpp_pipe)
4563d8817e4Smiod 	{
4573d8817e4Smiod 	  /* Sigh, try the default */
4583d8817e4Smiod 
4593d8817e4Smiod 	  cpp_pipe = look_for_default (cmd, "", 0, preprocargs, filename);
4603d8817e4Smiod 	}
4613d8817e4Smiod 
4623d8817e4Smiod     }
4633d8817e4Smiod 
4643d8817e4Smiod   free (cmd);
4653d8817e4Smiod 
4663d8817e4Smiod   rc_filename = xstrdup (filename);
4673d8817e4Smiod   rc_lineno = 1;
4683d8817e4Smiod   if (language != -1)
4693d8817e4Smiod     rcparse_set_language (language);
4703d8817e4Smiod   yyin = cpp_pipe;
4713d8817e4Smiod   yyparse ();
4723d8817e4Smiod   rcparse_discard_strings ();
4733d8817e4Smiod 
4743d8817e4Smiod   close_input_stream ();
4753d8817e4Smiod 
4763d8817e4Smiod   if (fontdirs != NULL)
4773d8817e4Smiod     define_fontdirs ();
4783d8817e4Smiod 
4793d8817e4Smiod   free (rc_filename);
4803d8817e4Smiod   rc_filename = NULL;
4813d8817e4Smiod 
4823d8817e4Smiod   return resources;
4833d8817e4Smiod }
4843d8817e4Smiod 
4853d8817e4Smiod /* Close the input stream if it is open.  */
4863d8817e4Smiod 
4873d8817e4Smiod static void
close_input_stream(void)4883d8817e4Smiod close_input_stream (void)
4893d8817e4Smiod {
4903d8817e4Smiod   if (istream_type == ISTREAM_FILE)
4913d8817e4Smiod     {
4923d8817e4Smiod       if (cpp_pipe != NULL)
4933d8817e4Smiod 	fclose (cpp_pipe);
4943d8817e4Smiod 
4953d8817e4Smiod       if (cpp_temp_file != NULL)
4963d8817e4Smiod 	{
4973d8817e4Smiod 	  int errno_save = errno;
4983d8817e4Smiod 
4993d8817e4Smiod 	  unlink (cpp_temp_file);
5003d8817e4Smiod 	  errno = errno_save;
5013d8817e4Smiod 	  free (cpp_temp_file);
5023d8817e4Smiod 	}
5033d8817e4Smiod     }
5043d8817e4Smiod   else
5053d8817e4Smiod     {
5063d8817e4Smiod       if (cpp_pipe != NULL)
5073d8817e4Smiod 	pclose (cpp_pipe);
5083d8817e4Smiod     }
5093d8817e4Smiod 
5103d8817e4Smiod   /* Since this is also run via xatexit, safeguard.  */
5113d8817e4Smiod   cpp_pipe = NULL;
5123d8817e4Smiod   cpp_temp_file = NULL;
5133d8817e4Smiod }
5143d8817e4Smiod 
5153d8817e4Smiod /* Report an error while reading an rc file.  */
5163d8817e4Smiod 
5173d8817e4Smiod void
yyerror(const char * msg)5183d8817e4Smiod yyerror (const char *msg)
5193d8817e4Smiod {
5203d8817e4Smiod   fatal ("%s:%d: %s", rc_filename, rc_lineno, msg);
5213d8817e4Smiod }
5223d8817e4Smiod 
5233d8817e4Smiod /* Issue a warning while reading an rc file.  */
5243d8817e4Smiod 
5253d8817e4Smiod void
rcparse_warning(const char * msg)5263d8817e4Smiod rcparse_warning (const char *msg)
5273d8817e4Smiod {
5283d8817e4Smiod   fprintf (stderr, _("%s:%d: %s\n"), rc_filename, rc_lineno, msg);
5293d8817e4Smiod }
5303d8817e4Smiod 
5313d8817e4Smiod /* Die if we get an unexpected end of file.  */
5323d8817e4Smiod 
5333d8817e4Smiod static void
unexpected_eof(const char * msg)5343d8817e4Smiod unexpected_eof (const char *msg)
5353d8817e4Smiod {
5363d8817e4Smiod   fatal (_("%s: unexpected EOF"), msg);
5373d8817e4Smiod }
5383d8817e4Smiod 
5393d8817e4Smiod /* Read a 16 bit word from a file.  The data is assumed to be little
5403d8817e4Smiod    endian.  */
5413d8817e4Smiod 
5423d8817e4Smiod static int
get_word(FILE * e,const char * msg)5433d8817e4Smiod get_word (FILE *e, const char *msg)
5443d8817e4Smiod {
5453d8817e4Smiod   int b1, b2;
5463d8817e4Smiod 
5473d8817e4Smiod   b1 = getc (e);
5483d8817e4Smiod   b2 = getc (e);
5493d8817e4Smiod   if (feof (e))
5503d8817e4Smiod     unexpected_eof (msg);
5513d8817e4Smiod   return ((b2 & 0xff) << 8) | (b1 & 0xff);
5523d8817e4Smiod }
5533d8817e4Smiod 
5543d8817e4Smiod /* Read a 32 bit word from a file.  The data is assumed to be little
5553d8817e4Smiod    endian.  */
5563d8817e4Smiod 
5573d8817e4Smiod static unsigned long
get_long(FILE * e,const char * msg)5583d8817e4Smiod get_long (FILE *e, const char *msg)
5593d8817e4Smiod {
5603d8817e4Smiod   int b1, b2, b3, b4;
5613d8817e4Smiod 
5623d8817e4Smiod   b1 = getc (e);
5633d8817e4Smiod   b2 = getc (e);
5643d8817e4Smiod   b3 = getc (e);
5653d8817e4Smiod   b4 = getc (e);
5663d8817e4Smiod   if (feof (e))
5673d8817e4Smiod     unexpected_eof (msg);
5683d8817e4Smiod   return (((((((b4 & 0xff) << 8)
5693d8817e4Smiod 	      | (b3 & 0xff)) << 8)
5703d8817e4Smiod 	    | (b2 & 0xff)) << 8)
5713d8817e4Smiod 	  | (b1 & 0xff));
5723d8817e4Smiod }
5733d8817e4Smiod 
5743d8817e4Smiod /* Read data from a file.  This is a wrapper to do error checking.  */
5753d8817e4Smiod 
5763d8817e4Smiod static void
get_data(FILE * e,unsigned char * p,unsigned long c,const char * msg)5773d8817e4Smiod get_data (FILE *e, unsigned char *p, unsigned long c, const char *msg)
5783d8817e4Smiod {
5793d8817e4Smiod   unsigned long got;
5803d8817e4Smiod 
5813d8817e4Smiod   got = fread (p, 1, c, e);
5823d8817e4Smiod   if (got == c)
5833d8817e4Smiod     return;
5843d8817e4Smiod 
5853d8817e4Smiod   fatal (_("%s: read of %lu returned %lu"), msg, c, got);
5863d8817e4Smiod }
5873d8817e4Smiod 
5883d8817e4Smiod /* Define an accelerator resource.  */
5893d8817e4Smiod 
5903d8817e4Smiod void
define_accelerator(struct res_id id,const struct res_res_info * resinfo,struct accelerator * data)5913d8817e4Smiod define_accelerator (struct res_id id, const struct res_res_info *resinfo,
5923d8817e4Smiod 		    struct accelerator *data)
5933d8817e4Smiod {
5943d8817e4Smiod   struct res_resource *r;
5953d8817e4Smiod 
5963d8817e4Smiod   r = define_standard_resource (&resources, RT_ACCELERATOR, id,
5973d8817e4Smiod 				resinfo->language, 0);
5983d8817e4Smiod   r->type = RES_TYPE_ACCELERATOR;
5993d8817e4Smiod   r->u.acc = data;
6003d8817e4Smiod   r->res_info = *resinfo;
6013d8817e4Smiod }
6023d8817e4Smiod 
6033d8817e4Smiod /* Define a bitmap resource.  Bitmap data is stored in a file.  The
6043d8817e4Smiod    first 14 bytes of the file are a standard header, which is not
6053d8817e4Smiod    included in the resource data.  */
6063d8817e4Smiod 
6073d8817e4Smiod #define BITMAP_SKIP (14)
6083d8817e4Smiod 
6093d8817e4Smiod void
define_bitmap(struct res_id id,const struct res_res_info * resinfo,const char * filename)6103d8817e4Smiod define_bitmap (struct res_id id, const struct res_res_info *resinfo,
6113d8817e4Smiod 	       const char *filename)
6123d8817e4Smiod {
6133d8817e4Smiod   FILE *e;
6143d8817e4Smiod   char *real_filename;
6153d8817e4Smiod   struct stat s;
6163d8817e4Smiod   unsigned char *data;
6173d8817e4Smiod   int i;
6183d8817e4Smiod   struct res_resource *r;
6193d8817e4Smiod 
6203d8817e4Smiod   e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename);
6213d8817e4Smiod 
6223d8817e4Smiod   if (stat (real_filename, &s) < 0)
6233d8817e4Smiod     fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
6243d8817e4Smiod 	   strerror (errno));
6253d8817e4Smiod 
6263d8817e4Smiod   data = (unsigned char *) res_alloc (s.st_size - BITMAP_SKIP);
6273d8817e4Smiod 
6283d8817e4Smiod   for (i = 0; i < BITMAP_SKIP; i++)
6293d8817e4Smiod     getc (e);
6303d8817e4Smiod 
6313d8817e4Smiod   get_data (e, data, s.st_size - BITMAP_SKIP, real_filename);
6323d8817e4Smiod 
6333d8817e4Smiod   fclose (e);
6343d8817e4Smiod   free (real_filename);
6353d8817e4Smiod 
6363d8817e4Smiod   r = define_standard_resource (&resources, RT_BITMAP, id,
6373d8817e4Smiod 				resinfo->language, 0);
6383d8817e4Smiod 
6393d8817e4Smiod   r->type = RES_TYPE_BITMAP;
6403d8817e4Smiod   r->u.data.length = s.st_size - BITMAP_SKIP;
6413d8817e4Smiod   r->u.data.data = data;
6423d8817e4Smiod   r->res_info = *resinfo;
6433d8817e4Smiod }
6443d8817e4Smiod 
6453d8817e4Smiod /* Define a cursor resource.  A cursor file may contain a set of
6463d8817e4Smiod    bitmaps, each representing the same cursor at various different
6473d8817e4Smiod    resolutions.  They each get written out with a different ID.  The
6483d8817e4Smiod    real cursor resource is then a group resource which can be used to
6493d8817e4Smiod    select one of the actual cursors.  */
6503d8817e4Smiod 
6513d8817e4Smiod void
define_cursor(struct res_id id,const struct res_res_info * resinfo,const char * filename)6523d8817e4Smiod define_cursor (struct res_id id, const struct res_res_info *resinfo,
6533d8817e4Smiod 	       const char *filename)
6543d8817e4Smiod {
6553d8817e4Smiod   FILE *e;
6563d8817e4Smiod   char *real_filename;
6573d8817e4Smiod   int type, count, i;
6583d8817e4Smiod   struct icondir *icondirs;
6593d8817e4Smiod   int first_cursor;
6603d8817e4Smiod   struct res_resource *r;
6613d8817e4Smiod   struct group_cursor *first, **pp;
6623d8817e4Smiod 
6633d8817e4Smiod   e = open_file_search (filename, FOPEN_RB, "cursor file", &real_filename);
6643d8817e4Smiod 
6653d8817e4Smiod   /* A cursor file is basically an icon file.  The start of the file
6663d8817e4Smiod      is a three word structure.  The first word is ignored.  The
6673d8817e4Smiod      second word is the type of data.  The third word is the number of
6683d8817e4Smiod      entries.  */
6693d8817e4Smiod 
6703d8817e4Smiod   get_word (e, real_filename);
6713d8817e4Smiod   type = get_word (e, real_filename);
6723d8817e4Smiod   count = get_word (e, real_filename);
6733d8817e4Smiod   if (type != 2)
6743d8817e4Smiod     fatal (_("cursor file `%s' does not contain cursor data"), real_filename);
6753d8817e4Smiod 
6763d8817e4Smiod   /* Read in the icon directory entries.  */
6773d8817e4Smiod 
6783d8817e4Smiod   icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
6793d8817e4Smiod 
6803d8817e4Smiod   for (i = 0; i < count; i++)
6813d8817e4Smiod     {
6823d8817e4Smiod       icondirs[i].width = getc (e);
6833d8817e4Smiod       icondirs[i].height = getc (e);
6843d8817e4Smiod       icondirs[i].colorcount = getc (e);
6853d8817e4Smiod       getc (e);
6863d8817e4Smiod       icondirs[i].u.cursor.xhotspot = get_word (e, real_filename);
6873d8817e4Smiod       icondirs[i].u.cursor.yhotspot = get_word (e, real_filename);
6883d8817e4Smiod       icondirs[i].bytes = get_long (e, real_filename);
6893d8817e4Smiod       icondirs[i].offset = get_long (e, real_filename);
6903d8817e4Smiod 
6913d8817e4Smiod       if (feof (e))
6923d8817e4Smiod 	unexpected_eof (real_filename);
6933d8817e4Smiod     }
6943d8817e4Smiod 
6953d8817e4Smiod   /* Define each cursor as a unique resource.  */
6963d8817e4Smiod 
6973d8817e4Smiod   first_cursor = cursors;
6983d8817e4Smiod 
6993d8817e4Smiod   for (i = 0; i < count; i++)
7003d8817e4Smiod     {
7013d8817e4Smiod       unsigned char *data;
7023d8817e4Smiod       struct res_id name;
7033d8817e4Smiod       struct cursor *c;
7043d8817e4Smiod 
7053d8817e4Smiod       if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
7063d8817e4Smiod 	fatal (_("%s: fseek to %lu failed: %s"), real_filename,
7073d8817e4Smiod 	       icondirs[i].offset, strerror (errno));
7083d8817e4Smiod 
7093d8817e4Smiod       data = (unsigned char *) res_alloc (icondirs[i].bytes);
7103d8817e4Smiod 
7113d8817e4Smiod       get_data (e, data, icondirs[i].bytes, real_filename);
7123d8817e4Smiod 
7133d8817e4Smiod       c = (struct cursor *) res_alloc (sizeof *c);
7143d8817e4Smiod       c->xhotspot = icondirs[i].u.cursor.xhotspot;
7153d8817e4Smiod       c->yhotspot = icondirs[i].u.cursor.yhotspot;
7163d8817e4Smiod       c->length = icondirs[i].bytes;
7173d8817e4Smiod       c->data = data;
7183d8817e4Smiod 
7193d8817e4Smiod       ++cursors;
7203d8817e4Smiod 
7213d8817e4Smiod       name.named = 0;
7223d8817e4Smiod       name.u.id = cursors;
7233d8817e4Smiod 
7243d8817e4Smiod       r = define_standard_resource (&resources, RT_CURSOR, name,
7253d8817e4Smiod 				    resinfo->language, 0);
7263d8817e4Smiod       r->type = RES_TYPE_CURSOR;
7273d8817e4Smiod       r->u.cursor = c;
7283d8817e4Smiod       r->res_info = *resinfo;
7293d8817e4Smiod     }
7303d8817e4Smiod 
7313d8817e4Smiod   fclose (e);
7323d8817e4Smiod   free (real_filename);
7333d8817e4Smiod 
7343d8817e4Smiod   /* Define a cursor group resource.  */
7353d8817e4Smiod 
7363d8817e4Smiod   first = NULL;
7373d8817e4Smiod   pp = &first;
7383d8817e4Smiod   for (i = 0; i < count; i++)
7393d8817e4Smiod     {
7403d8817e4Smiod       struct group_cursor *cg;
7413d8817e4Smiod 
7423d8817e4Smiod       cg = (struct group_cursor *) res_alloc (sizeof *cg);
7433d8817e4Smiod       cg->next = NULL;
7443d8817e4Smiod       cg->width = icondirs[i].width;
7453d8817e4Smiod       cg->height = 2 * icondirs[i].height;
7463d8817e4Smiod 
7473d8817e4Smiod       /* FIXME: What should these be set to?  */
7483d8817e4Smiod       cg->planes = 1;
7493d8817e4Smiod       cg->bits = 1;
7503d8817e4Smiod 
7513d8817e4Smiod       cg->bytes = icondirs[i].bytes + 4;
7523d8817e4Smiod       cg->index = first_cursor + i + 1;
7533d8817e4Smiod 
7543d8817e4Smiod       *pp = cg;
7553d8817e4Smiod       pp = &(*pp)->next;
7563d8817e4Smiod     }
7573d8817e4Smiod 
7583d8817e4Smiod   free (icondirs);
7593d8817e4Smiod 
7603d8817e4Smiod   r = define_standard_resource (&resources, RT_GROUP_CURSOR, id,
7613d8817e4Smiod 				resinfo->language, 0);
7623d8817e4Smiod   r->type = RES_TYPE_GROUP_CURSOR;
7633d8817e4Smiod   r->u.group_cursor = first;
7643d8817e4Smiod   r->res_info = *resinfo;
7653d8817e4Smiod }
7663d8817e4Smiod 
7673d8817e4Smiod /* Define a dialog resource.  */
7683d8817e4Smiod 
7693d8817e4Smiod void
define_dialog(struct res_id id,const struct res_res_info * resinfo,const struct dialog * dialog)7703d8817e4Smiod define_dialog (struct res_id id, const struct res_res_info *resinfo,
7713d8817e4Smiod 	       const struct dialog *dialog)
7723d8817e4Smiod {
7733d8817e4Smiod   struct dialog *copy;
7743d8817e4Smiod   struct res_resource *r;
7753d8817e4Smiod 
7763d8817e4Smiod   copy = (struct dialog *) res_alloc (sizeof *copy);
7773d8817e4Smiod   *copy = *dialog;
7783d8817e4Smiod 
7793d8817e4Smiod   r = define_standard_resource (&resources, RT_DIALOG, id,
7803d8817e4Smiod 				resinfo->language, 0);
7813d8817e4Smiod   r->type = RES_TYPE_DIALOG;
7823d8817e4Smiod   r->u.dialog = copy;
7833d8817e4Smiod   r->res_info = *resinfo;
7843d8817e4Smiod }
7853d8817e4Smiod 
7863d8817e4Smiod /* Define a dialog control.  This does not define a resource, but
7873d8817e4Smiod    merely allocates and fills in a structure.  */
7883d8817e4Smiod 
7893d8817e4Smiod struct dialog_control *
define_control(const struct res_id iid,unsigned long id,unsigned long x,unsigned long y,unsigned long width,unsigned long height,unsigned long class,unsigned long style,unsigned long exstyle)7903d8817e4Smiod define_control (const struct res_id iid, unsigned long id, unsigned long x,
7913d8817e4Smiod 		unsigned long y, unsigned long width, unsigned long height,
7923d8817e4Smiod 		unsigned long class, unsigned long style,
7933d8817e4Smiod 		unsigned long exstyle)
7943d8817e4Smiod {
7953d8817e4Smiod   struct dialog_control *n;
7963d8817e4Smiod 
7973d8817e4Smiod   n = (struct dialog_control *) res_alloc (sizeof *n);
7983d8817e4Smiod   n->next = NULL;
7993d8817e4Smiod   n->id = id;
8003d8817e4Smiod   n->style = style;
8013d8817e4Smiod   n->exstyle = exstyle;
8023d8817e4Smiod   n->x = x;
8033d8817e4Smiod   n->y = y;
8043d8817e4Smiod   n->width = width;
8053d8817e4Smiod   n->height = height;
8063d8817e4Smiod   n->class.named = 0;
8073d8817e4Smiod   n->class.u.id = class;
8083d8817e4Smiod   n->text = iid;
8093d8817e4Smiod   n->data = NULL;
8103d8817e4Smiod   n->help = 0;
8113d8817e4Smiod 
8123d8817e4Smiod   return n;
8133d8817e4Smiod }
8143d8817e4Smiod 
8153d8817e4Smiod struct dialog_control *
define_icon_control(struct res_id iid,unsigned long id,unsigned long x,unsigned long y,unsigned long style,unsigned long exstyle,unsigned long help,struct rcdata_item * data,struct dialog_ex * ex)8163d8817e4Smiod define_icon_control (struct res_id iid, unsigned long id, unsigned long x,
8173d8817e4Smiod 		     unsigned long y, unsigned long style,
8183d8817e4Smiod 		     unsigned long exstyle, unsigned long help,
8193d8817e4Smiod 		     struct rcdata_item *data, struct dialog_ex *ex)
8203d8817e4Smiod {
8213d8817e4Smiod   struct dialog_control *n;
8223d8817e4Smiod   struct res_id tid;
8233d8817e4Smiod 
8243d8817e4Smiod   if (style == 0)
8253d8817e4Smiod     style = SS_ICON | WS_CHILD | WS_VISIBLE;
8263d8817e4Smiod   res_string_to_id (&tid, "");
8273d8817e4Smiod   n = define_control (tid, id, x, y, 0, 0, CTL_STATIC, style, exstyle);
8283d8817e4Smiod   n->text = iid;
8293d8817e4Smiod   if (help && !ex)
8303d8817e4Smiod     rcparse_warning (_("help ID requires DIALOGEX"));
8313d8817e4Smiod   if (data && !ex)
8323d8817e4Smiod     rcparse_warning (_("control data requires DIALOGEX"));
8333d8817e4Smiod   n->help = help;
8343d8817e4Smiod   n->data = data;
8353d8817e4Smiod 
8363d8817e4Smiod   return n;
8373d8817e4Smiod }
8383d8817e4Smiod 
8393d8817e4Smiod /* Define a font resource.  */
8403d8817e4Smiod 
8413d8817e4Smiod void
define_font(struct res_id id,const struct res_res_info * resinfo,const char * filename)8423d8817e4Smiod define_font (struct res_id id, const struct res_res_info *resinfo,
8433d8817e4Smiod 	     const char *filename)
8443d8817e4Smiod {
8453d8817e4Smiod   FILE *e;
8463d8817e4Smiod   char *real_filename;
8473d8817e4Smiod   struct stat s;
8483d8817e4Smiod   unsigned char *data;
8493d8817e4Smiod   struct res_resource *r;
8503d8817e4Smiod   long offset;
8513d8817e4Smiod   long fontdatalength;
8523d8817e4Smiod   unsigned char *fontdata;
8533d8817e4Smiod   struct fontdir *fd;
8543d8817e4Smiod   const char *device, *face;
8553d8817e4Smiod   struct fontdir **pp;
8563d8817e4Smiod 
8573d8817e4Smiod   e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
8583d8817e4Smiod 
8593d8817e4Smiod   if (stat (real_filename, &s) < 0)
8603d8817e4Smiod     fatal (_("stat failed on font file `%s': %s"), real_filename,
8613d8817e4Smiod 	   strerror (errno));
8623d8817e4Smiod 
8633d8817e4Smiod   data = (unsigned char *) res_alloc (s.st_size);
8643d8817e4Smiod 
8653d8817e4Smiod   get_data (e, data, s.st_size, real_filename);
8663d8817e4Smiod 
8673d8817e4Smiod   fclose (e);
8683d8817e4Smiod   free (real_filename);
8693d8817e4Smiod 
8703d8817e4Smiod   r = define_standard_resource (&resources, RT_FONT, id,
8713d8817e4Smiod 				resinfo->language, 0);
8723d8817e4Smiod 
8733d8817e4Smiod   r->type = RES_TYPE_FONT;
8743d8817e4Smiod   r->u.data.length = s.st_size;
8753d8817e4Smiod   r->u.data.data = data;
8763d8817e4Smiod   r->res_info = *resinfo;
8773d8817e4Smiod 
8783d8817e4Smiod   /* For each font resource, we must add an entry in the FONTDIR
8793d8817e4Smiod      resource.  The FONTDIR resource includes some strings in the font
8803d8817e4Smiod      file.  To find them, we have to do some magic on the data we have
8813d8817e4Smiod      read.  */
8823d8817e4Smiod 
8833d8817e4Smiod   offset = ((((((data[47] << 8)
8843d8817e4Smiod 		| data[46]) << 8)
8853d8817e4Smiod 	      | data[45]) << 8)
8863d8817e4Smiod 	    | data[44]);
8873d8817e4Smiod   if (offset > 0 && offset < s.st_size)
8883d8817e4Smiod     device = (char *) data + offset;
8893d8817e4Smiod   else
8903d8817e4Smiod     device = "";
8913d8817e4Smiod 
8923d8817e4Smiod   offset = ((((((data[51] << 8)
8933d8817e4Smiod 		| data[50]) << 8)
8943d8817e4Smiod 	      | data[49]) << 8)
8953d8817e4Smiod 	    | data[48]);
8963d8817e4Smiod   if (offset > 0 && offset < s.st_size)
8973d8817e4Smiod     face = (char *) data + offset;
8983d8817e4Smiod   else
8993d8817e4Smiod     face = "";
9003d8817e4Smiod 
9013d8817e4Smiod   ++fonts;
9023d8817e4Smiod 
9033d8817e4Smiod   fontdatalength = 58 + strlen (device) + strlen (face);
9043d8817e4Smiod   fontdata = (unsigned char *) res_alloc (fontdatalength);
9053d8817e4Smiod   memcpy (fontdata, data, 56);
9063d8817e4Smiod   strcpy ((char *) fontdata + 56, device);
9073d8817e4Smiod   strcpy ((char *) fontdata + 57 + strlen (device), face);
9083d8817e4Smiod 
9093d8817e4Smiod   fd = (struct fontdir *) res_alloc (sizeof *fd);
9103d8817e4Smiod   fd->next = NULL;
9113d8817e4Smiod   fd->index = fonts;
9123d8817e4Smiod   fd->length = fontdatalength;
9133d8817e4Smiod   fd->data = fontdata;
9143d8817e4Smiod 
9153d8817e4Smiod   for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next)
9163d8817e4Smiod     ;
9173d8817e4Smiod   *pp = fd;
9183d8817e4Smiod 
9193d8817e4Smiod   /* For the single fontdirs resource, we always use the resource
9203d8817e4Smiod      information of the last font.  I don't know what else to do.  */
9213d8817e4Smiod   fontdirs_resinfo = *resinfo;
9223d8817e4Smiod }
9233d8817e4Smiod 
9243d8817e4Smiod /* Define the fontdirs resource.  This is called after the entire rc
9253d8817e4Smiod    file has been parsed, if any font resources were seen.  */
9263d8817e4Smiod 
9273d8817e4Smiod static void
define_fontdirs(void)9283d8817e4Smiod define_fontdirs (void)
9293d8817e4Smiod {
9303d8817e4Smiod   struct res_resource *r;
9313d8817e4Smiod   struct res_id id;
9323d8817e4Smiod 
9333d8817e4Smiod   id.named = 0;
9343d8817e4Smiod   id.u.id = 1;
9353d8817e4Smiod 
9363d8817e4Smiod   r = define_standard_resource (&resources, RT_FONTDIR, id, 0x409, 0);
9373d8817e4Smiod 
9383d8817e4Smiod   r->type = RES_TYPE_FONTDIR;
9393d8817e4Smiod   r->u.fontdir = fontdirs;
9403d8817e4Smiod   r->res_info = fontdirs_resinfo;
9413d8817e4Smiod }
9423d8817e4Smiod 
9433d8817e4Smiod /* Define an icon resource.  An icon file may contain a set of
9443d8817e4Smiod    bitmaps, each representing the same icon at various different
9453d8817e4Smiod    resolutions.  They each get written out with a different ID.  The
9463d8817e4Smiod    real icon resource is then a group resource which can be used to
9473d8817e4Smiod    select one of the actual icon bitmaps.  */
9483d8817e4Smiod 
9493d8817e4Smiod void
define_icon(struct res_id id,const struct res_res_info * resinfo,const char * filename)9503d8817e4Smiod define_icon (struct res_id id, const struct res_res_info *resinfo,
9513d8817e4Smiod 	     const char *filename)
9523d8817e4Smiod {
9533d8817e4Smiod   FILE *e;
9543d8817e4Smiod   char *real_filename;
9553d8817e4Smiod   int type, count, i;
9563d8817e4Smiod   struct icondir *icondirs;
9573d8817e4Smiod   int first_icon;
9583d8817e4Smiod   struct res_resource *r;
9593d8817e4Smiod   struct group_icon *first, **pp;
9603d8817e4Smiod 
9613d8817e4Smiod   e = open_file_search (filename, FOPEN_RB, "icon file", &real_filename);
9623d8817e4Smiod 
9633d8817e4Smiod   /* The start of an icon file is a three word structure.  The first
9643d8817e4Smiod      word is ignored.  The second word is the type of data.  The third
9653d8817e4Smiod      word is the number of entries.  */
9663d8817e4Smiod 
9673d8817e4Smiod   get_word (e, real_filename);
9683d8817e4Smiod   type = get_word (e, real_filename);
9693d8817e4Smiod   count = get_word (e, real_filename);
9703d8817e4Smiod   if (type != 1)
9713d8817e4Smiod     fatal (_("icon file `%s' does not contain icon data"), real_filename);
9723d8817e4Smiod 
9733d8817e4Smiod   /* Read in the icon directory entries.  */
9743d8817e4Smiod 
9753d8817e4Smiod   icondirs = (struct icondir *) xmalloc (count * sizeof *icondirs);
9763d8817e4Smiod 
9773d8817e4Smiod   for (i = 0; i < count; i++)
9783d8817e4Smiod     {
9793d8817e4Smiod       icondirs[i].width = getc (e);
9803d8817e4Smiod       icondirs[i].height = getc (e);
9813d8817e4Smiod       icondirs[i].colorcount = getc (e);
9823d8817e4Smiod       getc (e);
9833d8817e4Smiod       icondirs[i].u.icon.planes = get_word (e, real_filename);
9843d8817e4Smiod       icondirs[i].u.icon.bits = get_word (e, real_filename);
9853d8817e4Smiod       icondirs[i].bytes = get_long (e, real_filename);
9863d8817e4Smiod       icondirs[i].offset = get_long (e, real_filename);
9873d8817e4Smiod 
9883d8817e4Smiod       if (feof (e))
9893d8817e4Smiod 	unexpected_eof (real_filename);
9903d8817e4Smiod     }
9913d8817e4Smiod 
9923d8817e4Smiod   /* Define each icon as a unique resource.  */
9933d8817e4Smiod 
9943d8817e4Smiod   first_icon = icons;
9953d8817e4Smiod 
9963d8817e4Smiod   for (i = 0; i < count; i++)
9973d8817e4Smiod     {
9983d8817e4Smiod       unsigned char *data;
9993d8817e4Smiod       struct res_id name;
10003d8817e4Smiod 
10013d8817e4Smiod       if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
10023d8817e4Smiod 	fatal (_("%s: fseek to %lu failed: %s"), real_filename,
10033d8817e4Smiod 	       icondirs[i].offset, strerror (errno));
10043d8817e4Smiod 
10053d8817e4Smiod       data = (unsigned char *) res_alloc (icondirs[i].bytes);
10063d8817e4Smiod 
10073d8817e4Smiod       get_data (e, data, icondirs[i].bytes, real_filename);
10083d8817e4Smiod 
10093d8817e4Smiod       ++icons;
10103d8817e4Smiod 
10113d8817e4Smiod       name.named = 0;
10123d8817e4Smiod       name.u.id = icons;
10133d8817e4Smiod 
10143d8817e4Smiod       r = define_standard_resource (&resources, RT_ICON, name,
10153d8817e4Smiod 				    resinfo->language, 0);
10163d8817e4Smiod       r->type = RES_TYPE_ICON;
10173d8817e4Smiod       r->u.data.length = icondirs[i].bytes;
10183d8817e4Smiod       r->u.data.data = data;
10193d8817e4Smiod       r->res_info = *resinfo;
10203d8817e4Smiod     }
10213d8817e4Smiod 
10223d8817e4Smiod   fclose (e);
10233d8817e4Smiod   free (real_filename);
10243d8817e4Smiod 
10253d8817e4Smiod   /* Define an icon group resource.  */
10263d8817e4Smiod 
10273d8817e4Smiod   first = NULL;
10283d8817e4Smiod   pp = &first;
10293d8817e4Smiod   for (i = 0; i < count; i++)
10303d8817e4Smiod     {
10313d8817e4Smiod       struct group_icon *cg;
10323d8817e4Smiod 
10333d8817e4Smiod       /* For some reason, at least in some files the planes and bits
10343d8817e4Smiod          are zero.  We instead set them from the color.  This is
10353d8817e4Smiod          copied from rcl.  */
10363d8817e4Smiod 
10373d8817e4Smiod       cg = (struct group_icon *) res_alloc (sizeof *cg);
10383d8817e4Smiod       cg->next = NULL;
10393d8817e4Smiod       cg->width = icondirs[i].width;
10403d8817e4Smiod       cg->height = icondirs[i].height;
10413d8817e4Smiod       cg->colors = icondirs[i].colorcount;
10423d8817e4Smiod 
10433d8817e4Smiod       if (icondirs[i].u.icon.planes)
10443d8817e4Smiod 	cg->planes = icondirs[i].u.icon.planes;
10453d8817e4Smiod       else
10463d8817e4Smiod 	cg->planes = 1;
10473d8817e4Smiod 
10483d8817e4Smiod       if (icondirs[i].u.icon.bits)
10493d8817e4Smiod 	cg->bits = icondirs[i].u.icon.bits;
10503d8817e4Smiod       else
10513d8817e4Smiod 	{
10523d8817e4Smiod 	  cg->bits = 0;
10533d8817e4Smiod 
10543d8817e4Smiod 	  while ((1L << cg->bits) < cg->colors)
10553d8817e4Smiod 	    ++cg->bits;
10563d8817e4Smiod 	}
10573d8817e4Smiod 
10583d8817e4Smiod       cg->bytes = icondirs[i].bytes;
10593d8817e4Smiod       cg->index = first_icon + i + 1;
10603d8817e4Smiod 
10613d8817e4Smiod       *pp = cg;
10623d8817e4Smiod       pp = &(*pp)->next;
10633d8817e4Smiod     }
10643d8817e4Smiod 
10653d8817e4Smiod   free (icondirs);
10663d8817e4Smiod 
10673d8817e4Smiod   r = define_standard_resource (&resources, RT_GROUP_ICON, id,
10683d8817e4Smiod 				resinfo->language, 0);
10693d8817e4Smiod   r->type = RES_TYPE_GROUP_ICON;
10703d8817e4Smiod   r->u.group_icon = first;
10713d8817e4Smiod   r->res_info = *resinfo;
10723d8817e4Smiod }
10733d8817e4Smiod 
10743d8817e4Smiod /* Define a menu resource.  */
10753d8817e4Smiod 
10763d8817e4Smiod void
define_menu(struct res_id id,const struct res_res_info * resinfo,struct menuitem * menuitems)10773d8817e4Smiod define_menu (struct res_id id, const struct res_res_info *resinfo,
10783d8817e4Smiod 	     struct menuitem *menuitems)
10793d8817e4Smiod {
10803d8817e4Smiod   struct menu *m;
10813d8817e4Smiod   struct res_resource *r;
10823d8817e4Smiod 
10833d8817e4Smiod   m = (struct menu *) res_alloc (sizeof *m);
10843d8817e4Smiod   m->items = menuitems;
10853d8817e4Smiod   m->help = 0;
10863d8817e4Smiod 
10873d8817e4Smiod   r = define_standard_resource (&resources, RT_MENU, id, resinfo->language, 0);
10883d8817e4Smiod   r->type = RES_TYPE_MENU;
10893d8817e4Smiod   r->u.menu = m;
10903d8817e4Smiod   r->res_info = *resinfo;
10913d8817e4Smiod }
10923d8817e4Smiod 
10933d8817e4Smiod /* Define a menu item.  This does not define a resource, but merely
10943d8817e4Smiod    allocates and fills in a structure.  */
10953d8817e4Smiod 
10963d8817e4Smiod struct menuitem *
define_menuitem(const char * text,int menuid,unsigned long type,unsigned long state,unsigned long help,struct menuitem * menuitems)10973d8817e4Smiod define_menuitem (const char *text, int menuid, unsigned long type,
10983d8817e4Smiod 		 unsigned long state, unsigned long help,
10993d8817e4Smiod 		 struct menuitem *menuitems)
11003d8817e4Smiod {
11013d8817e4Smiod   struct menuitem *mi;
11023d8817e4Smiod 
11033d8817e4Smiod   mi = (struct menuitem *) res_alloc (sizeof *mi);
11043d8817e4Smiod   mi->next = NULL;
11053d8817e4Smiod   mi->type = type;
11063d8817e4Smiod   mi->state = state;
11073d8817e4Smiod   mi->id = menuid;
11083d8817e4Smiod   if (text == NULL)
11093d8817e4Smiod     mi->text = NULL;
11103d8817e4Smiod   else
11113d8817e4Smiod     unicode_from_ascii ((int *) NULL, &mi->text, text);
11123d8817e4Smiod   mi->help = help;
11133d8817e4Smiod   mi->popup = menuitems;
11143d8817e4Smiod   return mi;
11153d8817e4Smiod }
11163d8817e4Smiod 
11173d8817e4Smiod /* Define a messagetable resource.  */
11183d8817e4Smiod 
11193d8817e4Smiod void
define_messagetable(struct res_id id,const struct res_res_info * resinfo,const char * filename)11203d8817e4Smiod define_messagetable (struct res_id id, const struct res_res_info *resinfo,
11213d8817e4Smiod 		     const char *filename)
11223d8817e4Smiod {
11233d8817e4Smiod   FILE *e;
11243d8817e4Smiod   char *real_filename;
11253d8817e4Smiod   struct stat s;
11263d8817e4Smiod   unsigned char *data;
11273d8817e4Smiod   struct res_resource *r;
11283d8817e4Smiod 
11293d8817e4Smiod   e = open_file_search (filename, FOPEN_RB, "messagetable file",
11303d8817e4Smiod 			&real_filename);
11313d8817e4Smiod 
11323d8817e4Smiod   if (stat (real_filename, &s) < 0)
11333d8817e4Smiod     fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
11343d8817e4Smiod 	   strerror (errno));
11353d8817e4Smiod 
11363d8817e4Smiod   data = (unsigned char *) res_alloc (s.st_size);
11373d8817e4Smiod 
11383d8817e4Smiod   get_data (e, data, s.st_size, real_filename);
11393d8817e4Smiod 
11403d8817e4Smiod   fclose (e);
11413d8817e4Smiod   free (real_filename);
11423d8817e4Smiod 
11433d8817e4Smiod   r = define_standard_resource (&resources, RT_MESSAGETABLE, id,
11443d8817e4Smiod 				resinfo->language, 0);
11453d8817e4Smiod 
11463d8817e4Smiod   r->type = RES_TYPE_MESSAGETABLE;
11473d8817e4Smiod   r->u.data.length = s.st_size;
11483d8817e4Smiod   r->u.data.data = data;
11493d8817e4Smiod   r->res_info = *resinfo;
11503d8817e4Smiod }
11513d8817e4Smiod 
11523d8817e4Smiod /* Define an rcdata resource.  */
11533d8817e4Smiod 
11543d8817e4Smiod void
define_rcdata(struct res_id id,const struct res_res_info * resinfo,struct rcdata_item * data)11553d8817e4Smiod define_rcdata (struct res_id id, const struct res_res_info *resinfo,
11563d8817e4Smiod 	       struct rcdata_item *data)
11573d8817e4Smiod {
11583d8817e4Smiod   struct res_resource *r;
11593d8817e4Smiod 
11603d8817e4Smiod   r = define_standard_resource (&resources, RT_RCDATA, id,
11613d8817e4Smiod 				resinfo->language, 0);
11623d8817e4Smiod   r->type = RES_TYPE_RCDATA;
11633d8817e4Smiod   r->u.rcdata = data;
11643d8817e4Smiod   r->res_info = *resinfo;
11653d8817e4Smiod }
11663d8817e4Smiod 
11673d8817e4Smiod /* Create an rcdata item holding a string.  */
11683d8817e4Smiod 
11693d8817e4Smiod struct rcdata_item *
define_rcdata_string(const char * string,unsigned long len)11703d8817e4Smiod define_rcdata_string (const char *string, unsigned long len)
11713d8817e4Smiod {
11723d8817e4Smiod   struct rcdata_item *ri;
11733d8817e4Smiod   char *s;
11743d8817e4Smiod 
11753d8817e4Smiod   ri = (struct rcdata_item *) res_alloc (sizeof *ri);
11763d8817e4Smiod   ri->next = NULL;
11773d8817e4Smiod   ri->type = RCDATA_STRING;
11783d8817e4Smiod   ri->u.string.length = len;
11793d8817e4Smiod   s = (char *) res_alloc (len);
11803d8817e4Smiod   memcpy (s, string, len);
11813d8817e4Smiod   ri->u.string.s = s;
11823d8817e4Smiod 
11833d8817e4Smiod   return ri;
11843d8817e4Smiod }
11853d8817e4Smiod 
11863d8817e4Smiod /* Create an rcdata item holding a number.  */
11873d8817e4Smiod 
11883d8817e4Smiod struct rcdata_item *
define_rcdata_number(unsigned long val,int dword)11893d8817e4Smiod define_rcdata_number (unsigned long val, int dword)
11903d8817e4Smiod {
11913d8817e4Smiod   struct rcdata_item *ri;
11923d8817e4Smiod 
11933d8817e4Smiod   ri = (struct rcdata_item *) res_alloc (sizeof *ri);
11943d8817e4Smiod   ri->next = NULL;
11953d8817e4Smiod   ri->type = dword ? RCDATA_DWORD : RCDATA_WORD;
11963d8817e4Smiod   ri->u.word = val;
11973d8817e4Smiod 
11983d8817e4Smiod   return ri;
11993d8817e4Smiod }
12003d8817e4Smiod 
12013d8817e4Smiod /* Define a stringtable resource.  This is called for each string
12023d8817e4Smiod    which appears in a STRINGTABLE statement.  */
12033d8817e4Smiod 
12043d8817e4Smiod void
define_stringtable(const struct res_res_info * resinfo,unsigned long stringid,const char * string)12053d8817e4Smiod define_stringtable (const struct res_res_info *resinfo,
12063d8817e4Smiod 		    unsigned long stringid, const char *string)
12073d8817e4Smiod {
12083d8817e4Smiod   struct res_id id;
12093d8817e4Smiod   struct res_resource *r;
12103d8817e4Smiod 
12113d8817e4Smiod   id.named = 0;
12123d8817e4Smiod   id.u.id = (stringid >> 4) + 1;
12133d8817e4Smiod   r = define_standard_resource (&resources, RT_STRING, id,
12143d8817e4Smiod 				resinfo->language, 1);
12153d8817e4Smiod 
12163d8817e4Smiod   if (r->type == RES_TYPE_UNINITIALIZED)
12173d8817e4Smiod     {
12183d8817e4Smiod       int i;
12193d8817e4Smiod 
12203d8817e4Smiod       r->type = RES_TYPE_STRINGTABLE;
12213d8817e4Smiod       r->u.stringtable = ((struct stringtable *)
12223d8817e4Smiod 			  res_alloc (sizeof (struct stringtable)));
12233d8817e4Smiod       for (i = 0; i < 16; i++)
12243d8817e4Smiod 	{
12253d8817e4Smiod 	  r->u.stringtable->strings[i].length = 0;
12263d8817e4Smiod 	  r->u.stringtable->strings[i].string = NULL;
12273d8817e4Smiod 	}
12283d8817e4Smiod 
12293d8817e4Smiod       r->res_info = *resinfo;
12303d8817e4Smiod     }
12313d8817e4Smiod 
12323d8817e4Smiod   unicode_from_ascii (&r->u.stringtable->strings[stringid & 0xf].length,
12333d8817e4Smiod 		      &r->u.stringtable->strings[stringid & 0xf].string,
12343d8817e4Smiod 		      string);
12353d8817e4Smiod }
12363d8817e4Smiod 
12373d8817e4Smiod /* Define a user data resource where the data is in the rc file.  */
12383d8817e4Smiod 
12393d8817e4Smiod void
define_user_data(struct res_id id,struct res_id type,const struct res_res_info * resinfo,struct rcdata_item * data)12403d8817e4Smiod define_user_data (struct res_id id, struct res_id type,
12413d8817e4Smiod 		  const struct res_res_info *resinfo,
12423d8817e4Smiod 		  struct rcdata_item *data)
12433d8817e4Smiod {
12443d8817e4Smiod   struct res_id ids[3];
12453d8817e4Smiod   struct res_resource *r;
12463d8817e4Smiod 
12473d8817e4Smiod   ids[0] = type;
12483d8817e4Smiod   ids[1] = id;
12493d8817e4Smiod   ids[2].named = 0;
12503d8817e4Smiod   ids[2].u.id = resinfo->language;
12513d8817e4Smiod 
12523d8817e4Smiod   r = define_resource (& resources, 3, ids, 0);
12533d8817e4Smiod   r->type = RES_TYPE_USERDATA;
12543d8817e4Smiod   r->u.userdata = data;
12553d8817e4Smiod   r->res_info = *resinfo;
12563d8817e4Smiod }
12573d8817e4Smiod 
12583d8817e4Smiod void
define_rcdata_file(struct res_id id,const struct res_res_info * resinfo,const char * filename)12593d8817e4Smiod define_rcdata_file (struct res_id id, const struct res_res_info *resinfo,
12603d8817e4Smiod 		    const char *filename)
12613d8817e4Smiod {
12623d8817e4Smiod   struct rcdata_item *ri;
12633d8817e4Smiod   FILE *e;
12643d8817e4Smiod   char *real_filename;
12653d8817e4Smiod   struct stat s;
12663d8817e4Smiod   unsigned char *data;
12673d8817e4Smiod 
12683d8817e4Smiod   e = open_file_search (filename, FOPEN_RB, "file", &real_filename);
12693d8817e4Smiod 
12703d8817e4Smiod 
12713d8817e4Smiod   if (stat (real_filename, &s) < 0)
12723d8817e4Smiod     fatal (_("stat failed on file `%s': %s"), real_filename,
12733d8817e4Smiod 	   strerror (errno));
12743d8817e4Smiod 
12753d8817e4Smiod   data = (unsigned char *) res_alloc (s.st_size);
12763d8817e4Smiod 
12773d8817e4Smiod   get_data (e, data, s.st_size, real_filename);
12783d8817e4Smiod 
12793d8817e4Smiod   fclose (e);
12803d8817e4Smiod   free (real_filename);
12813d8817e4Smiod 
12823d8817e4Smiod   ri = (struct rcdata_item *) res_alloc (sizeof *ri);
12833d8817e4Smiod   ri->next = NULL;
12843d8817e4Smiod   ri->type = RCDATA_BUFFER;
12853d8817e4Smiod   ri->u.buffer.length = s.st_size;
12863d8817e4Smiod   ri->u.buffer.data = data;
12873d8817e4Smiod 
12883d8817e4Smiod   define_rcdata (id, resinfo, ri);
12893d8817e4Smiod }
12903d8817e4Smiod 
12913d8817e4Smiod /* Define a user data resource where the data is in a file.  */
12923d8817e4Smiod 
12933d8817e4Smiod void
define_user_file(struct res_id id,struct res_id type,const struct res_res_info * resinfo,const char * filename)12943d8817e4Smiod define_user_file (struct res_id id, struct res_id type,
12953d8817e4Smiod 		  const struct res_res_info *resinfo, const char *filename)
12963d8817e4Smiod {
12973d8817e4Smiod   FILE *e;
12983d8817e4Smiod   char *real_filename;
12993d8817e4Smiod   struct stat s;
13003d8817e4Smiod   unsigned char *data;
13013d8817e4Smiod   struct res_id ids[3];
13023d8817e4Smiod   struct res_resource *r;
13033d8817e4Smiod 
13043d8817e4Smiod   e = open_file_search (filename, FOPEN_RB, "file", &real_filename);
13053d8817e4Smiod 
13063d8817e4Smiod   if (stat (real_filename, &s) < 0)
13073d8817e4Smiod     fatal (_("stat failed on file `%s': %s"), real_filename,
13083d8817e4Smiod 	   strerror (errno));
13093d8817e4Smiod 
13103d8817e4Smiod   data = (unsigned char *) res_alloc (s.st_size);
13113d8817e4Smiod 
13123d8817e4Smiod   get_data (e, data, s.st_size, real_filename);
13133d8817e4Smiod 
13143d8817e4Smiod   fclose (e);
13153d8817e4Smiod   free (real_filename);
13163d8817e4Smiod 
13173d8817e4Smiod   ids[0] = type;
13183d8817e4Smiod   ids[1] = id;
13193d8817e4Smiod   ids[2].named = 0;
13203d8817e4Smiod   ids[2].u.id = resinfo->language;
13213d8817e4Smiod 
13223d8817e4Smiod   r = define_resource (&resources, 3, ids, 0);
13233d8817e4Smiod   r->type = RES_TYPE_USERDATA;
13243d8817e4Smiod   r->u.userdata = ((struct rcdata_item *)
13253d8817e4Smiod 		   res_alloc (sizeof (struct rcdata_item)));
13263d8817e4Smiod   r->u.userdata->next = NULL;
13273d8817e4Smiod   r->u.userdata->type = RCDATA_BUFFER;
13283d8817e4Smiod   r->u.userdata->u.buffer.length = s.st_size;
13293d8817e4Smiod   r->u.userdata->u.buffer.data = data;
13303d8817e4Smiod   r->res_info = *resinfo;
13313d8817e4Smiod }
13323d8817e4Smiod 
13333d8817e4Smiod /* Define a versioninfo resource.  */
13343d8817e4Smiod 
13353d8817e4Smiod void
define_versioninfo(struct res_id id,int language,struct fixed_versioninfo * fixedverinfo,struct ver_info * verinfo)13363d8817e4Smiod define_versioninfo (struct res_id id, int language,
13373d8817e4Smiod 		    struct fixed_versioninfo *fixedverinfo,
13383d8817e4Smiod 		    struct ver_info *verinfo)
13393d8817e4Smiod {
13403d8817e4Smiod   struct res_resource *r;
13413d8817e4Smiod 
13423d8817e4Smiod   r = define_standard_resource (&resources, RT_VERSION, id, language, 0);
13433d8817e4Smiod   r->type = RES_TYPE_VERSIONINFO;
13443d8817e4Smiod   r->u.versioninfo = ((struct versioninfo *)
13453d8817e4Smiod 		      res_alloc (sizeof (struct versioninfo)));
13463d8817e4Smiod   r->u.versioninfo->fixed = fixedverinfo;
13473d8817e4Smiod   r->u.versioninfo->var = verinfo;
13483d8817e4Smiod   r->res_info.language = language;
13493d8817e4Smiod }
13503d8817e4Smiod 
13513d8817e4Smiod /* Add string version info to a list of version information.  */
13523d8817e4Smiod 
13533d8817e4Smiod struct ver_info *
append_ver_stringfileinfo(struct ver_info * verinfo,const char * language,struct ver_stringinfo * strings)13543d8817e4Smiod append_ver_stringfileinfo (struct ver_info *verinfo, const char *language,
13553d8817e4Smiod 			   struct ver_stringinfo *strings)
13563d8817e4Smiod {
13573d8817e4Smiod   struct ver_info *vi, **pp;
13583d8817e4Smiod 
13593d8817e4Smiod   vi = (struct ver_info *) res_alloc (sizeof *vi);
13603d8817e4Smiod   vi->next = NULL;
13613d8817e4Smiod   vi->type = VERINFO_STRING;
13623d8817e4Smiod   unicode_from_ascii ((int *) NULL, &vi->u.string.language, language);
13633d8817e4Smiod   vi->u.string.strings = strings;
13643d8817e4Smiod 
13653d8817e4Smiod   for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
13663d8817e4Smiod     ;
13673d8817e4Smiod   *pp = vi;
13683d8817e4Smiod 
13693d8817e4Smiod   return verinfo;
13703d8817e4Smiod }
13713d8817e4Smiod 
13723d8817e4Smiod /* Add variable version info to a list of version information.  */
13733d8817e4Smiod 
13743d8817e4Smiod struct ver_info *
append_ver_varfileinfo(struct ver_info * verinfo,const char * key,struct ver_varinfo * var)13753d8817e4Smiod append_ver_varfileinfo (struct ver_info *verinfo, const char *key,
13763d8817e4Smiod 			struct ver_varinfo *var)
13773d8817e4Smiod {
13783d8817e4Smiod   struct ver_info *vi, **pp;
13793d8817e4Smiod 
13803d8817e4Smiod   vi = (struct ver_info *) res_alloc (sizeof *vi);
13813d8817e4Smiod   vi->next = NULL;
13823d8817e4Smiod   vi->type = VERINFO_VAR;
13833d8817e4Smiod   unicode_from_ascii ((int *) NULL, &vi->u.var.key, key);
13843d8817e4Smiod   vi->u.var.var = var;
13853d8817e4Smiod 
13863d8817e4Smiod   for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
13873d8817e4Smiod     ;
13883d8817e4Smiod   *pp = vi;
13893d8817e4Smiod 
13903d8817e4Smiod   return verinfo;
13913d8817e4Smiod }
13923d8817e4Smiod 
13933d8817e4Smiod /* Append version string information to a list.  */
13943d8817e4Smiod 
13953d8817e4Smiod struct ver_stringinfo *
append_verval(struct ver_stringinfo * strings,const char * key,const char * value)13963d8817e4Smiod append_verval (struct ver_stringinfo *strings, const char *key,
13973d8817e4Smiod 	       const char *value)
13983d8817e4Smiod {
13993d8817e4Smiod   struct ver_stringinfo *vs, **pp;
14003d8817e4Smiod 
14013d8817e4Smiod   vs = (struct ver_stringinfo *) res_alloc (sizeof *vs);
14023d8817e4Smiod   vs->next = NULL;
14033d8817e4Smiod   unicode_from_ascii ((int *) NULL, &vs->key, key);
14043d8817e4Smiod   unicode_from_ascii ((int *) NULL, &vs->value, value);
14053d8817e4Smiod 
14063d8817e4Smiod   for (pp = &strings; *pp != NULL; pp = &(*pp)->next)
14073d8817e4Smiod     ;
14083d8817e4Smiod   *pp = vs;
14093d8817e4Smiod 
14103d8817e4Smiod   return strings;
14113d8817e4Smiod }
14123d8817e4Smiod 
14133d8817e4Smiod /* Append version variable information to a list.  */
14143d8817e4Smiod 
14153d8817e4Smiod struct ver_varinfo *
append_vertrans(struct ver_varinfo * var,unsigned long language,unsigned long charset)14163d8817e4Smiod append_vertrans (struct ver_varinfo *var, unsigned long language,
14173d8817e4Smiod 		 unsigned long charset)
14183d8817e4Smiod {
14193d8817e4Smiod   struct ver_varinfo *vv, **pp;
14203d8817e4Smiod 
14213d8817e4Smiod   vv = (struct ver_varinfo *) res_alloc (sizeof *vv);
14223d8817e4Smiod   vv->next = NULL;
14233d8817e4Smiod   vv->language = language;
14243d8817e4Smiod   vv->charset = charset;
14253d8817e4Smiod 
14263d8817e4Smiod   for (pp = &var; *pp != NULL; pp = &(*pp)->next)
14273d8817e4Smiod     ;
14283d8817e4Smiod   *pp = vv;
14293d8817e4Smiod 
14303d8817e4Smiod   return var;
14313d8817e4Smiod }
14323d8817e4Smiod 
14333d8817e4Smiod /* Local functions used to write out an rc file.  */
14343d8817e4Smiod 
14353d8817e4Smiod static void indent (FILE *, int);
14363d8817e4Smiod static void write_rc_directory
14373d8817e4Smiod   (FILE *, const struct res_directory *, const struct res_id *,
14383d8817e4Smiod    const struct res_id *, int *, int);
14393d8817e4Smiod static void write_rc_subdir
14403d8817e4Smiod   (FILE *, const struct res_entry *, const struct res_id *,
14413d8817e4Smiod    const struct res_id *, int *, int);
14423d8817e4Smiod static void write_rc_resource
14433d8817e4Smiod   (FILE *, const struct res_id *, const struct res_id *,
14443d8817e4Smiod    const struct res_resource *, int *);
14453d8817e4Smiod static void write_rc_accelerators (FILE *, const struct accelerator *);
14463d8817e4Smiod static void write_rc_cursor (FILE *, const struct cursor *);
14473d8817e4Smiod static void write_rc_group_cursor (FILE *, const struct group_cursor *);
14483d8817e4Smiod static void write_rc_dialog (FILE *, const struct dialog *);
14493d8817e4Smiod static void write_rc_dialog_control (FILE *, const struct dialog_control *);
14503d8817e4Smiod static void write_rc_fontdir (FILE *, const struct fontdir *);
14513d8817e4Smiod static void write_rc_group_icon (FILE *, const struct group_icon *);
14523d8817e4Smiod static void write_rc_menu (FILE *, const struct menu *, int);
14533d8817e4Smiod static void write_rc_menuitems (FILE *, const struct menuitem *, int, int);
14543d8817e4Smiod static void write_rc_rcdata (FILE *, const struct rcdata_item *, int);
14553d8817e4Smiod static void write_rc_stringtable
14563d8817e4Smiod   (FILE *, const struct res_id *, const struct stringtable *);
14573d8817e4Smiod static void write_rc_versioninfo (FILE *, const struct versioninfo *);
14583d8817e4Smiod static void write_rc_filedata (FILE *, unsigned long, const unsigned char *);
14593d8817e4Smiod 
14603d8817e4Smiod /* Indent a given number of spaces.  */
14613d8817e4Smiod 
14623d8817e4Smiod static void
indent(FILE * e,int c)14633d8817e4Smiod indent (FILE *e, int c)
14643d8817e4Smiod {
14653d8817e4Smiod   int i;
14663d8817e4Smiod 
14673d8817e4Smiod   for (i = 0; i < c; i++)
14683d8817e4Smiod     putc (' ', e);
14693d8817e4Smiod }
14703d8817e4Smiod 
14713d8817e4Smiod /* Dump the resources we have read in the format of an rc file.
14723d8817e4Smiod 
14733d8817e4Smiod    Actually, we don't use the format of an rc file, because it's way
14743d8817e4Smiod    too much of a pain--for example, we'd have to write icon resources
14753d8817e4Smiod    into a file and refer to that file.  We just generate a readable
14763d8817e4Smiod    format that kind of looks like an rc file, and is useful for
14773d8817e4Smiod    understanding the contents of a resource file.  Someday we may want
14783d8817e4Smiod    to generate an rc file which the rc compiler can read; if that day
14793d8817e4Smiod    comes, this code will have to be fixed up.  */
14803d8817e4Smiod 
14813d8817e4Smiod void
write_rc_file(const char * filename,const struct res_directory * resources)14823d8817e4Smiod write_rc_file (const char *filename, const struct res_directory *resources)
14833d8817e4Smiod {
14843d8817e4Smiod   FILE *e;
14853d8817e4Smiod   int language;
14863d8817e4Smiod 
14873d8817e4Smiod   if (filename == NULL)
14883d8817e4Smiod     e = stdout;
14893d8817e4Smiod   else
14903d8817e4Smiod     {
14913d8817e4Smiod       e = fopen (filename, FOPEN_WT);
14923d8817e4Smiod       if (e == NULL)
14933d8817e4Smiod 	fatal (_("can't open `%s' for output: %s"), filename, strerror (errno));
14943d8817e4Smiod     }
14953d8817e4Smiod 
14963d8817e4Smiod   language = -1;
14973d8817e4Smiod   write_rc_directory (e, resources, (const struct res_id *) NULL,
14983d8817e4Smiod 		      (const struct res_id *) NULL, &language, 1);
14993d8817e4Smiod }
15003d8817e4Smiod 
15013d8817e4Smiod /* Write out a directory.  E is the file to write to.  RD is the
15023d8817e4Smiod    directory.  TYPE is a pointer to the level 1 ID which serves as the
15033d8817e4Smiod    resource type.  NAME is a pointer to the level 2 ID which serves as
15043d8817e4Smiod    an individual resource name.  LANGUAGE is a pointer to the current
15053d8817e4Smiod    language.  LEVEL is the level in the tree.  */
15063d8817e4Smiod 
15073d8817e4Smiod static void
write_rc_directory(FILE * e,const struct res_directory * rd,const struct res_id * type,const struct res_id * name,int * language,int level)15083d8817e4Smiod write_rc_directory (FILE *e, const struct res_directory *rd,
15093d8817e4Smiod 		    const struct res_id *type, const struct res_id *name,
15103d8817e4Smiod 		    int *language, int level)
15113d8817e4Smiod {
15123d8817e4Smiod   const struct res_entry *re;
15133d8817e4Smiod 
15143d8817e4Smiod   /* Print out some COFF information that rc files can't represent.  */
15153d8817e4Smiod 
15163d8817e4Smiod   if (rd->time != 0)
15173d8817e4Smiod     fprintf (e, "// Time stamp: %lu\n", rd->time);
15183d8817e4Smiod   if (rd->characteristics != 0)
15193d8817e4Smiod     fprintf (e, "// Characteristics: %lu\n", rd->characteristics);
15203d8817e4Smiod   if (rd->major != 0 || rd->minor != 0)
15213d8817e4Smiod     fprintf (e, "// Version: %d %d\n", rd->major, rd->minor);
15223d8817e4Smiod 
15233d8817e4Smiod   for (re = rd->entries;  re != NULL; re = re->next)
15243d8817e4Smiod     {
15253d8817e4Smiod       switch (level)
15263d8817e4Smiod 	{
15273d8817e4Smiod 	case 1:
15283d8817e4Smiod 	  /* If we're at level 1, the key of this resource is the
15293d8817e4Smiod              type.  This normally duplicates the information we have
15303d8817e4Smiod              stored with the resource itself, but we need to remember
15313d8817e4Smiod              the type if this is a user define resource type.  */
15323d8817e4Smiod 	  type = &re->id;
15333d8817e4Smiod 	  break;
15343d8817e4Smiod 
15353d8817e4Smiod 	case 2:
15363d8817e4Smiod 	  /* If we're at level 2, the key of this resource is the name
15373d8817e4Smiod 	     we are going to use in the rc printout.  */
15383d8817e4Smiod 	  name = &re->id;
15393d8817e4Smiod 	  break;
15403d8817e4Smiod 
15413d8817e4Smiod 	case 3:
15423d8817e4Smiod 	  /* If we're at level 3, then this key represents a language.
15433d8817e4Smiod 	     Use it to update the current language.  */
15443d8817e4Smiod 	  if (! re->id.named
15453d8817e4Smiod 	      && re->id.u.id != (unsigned long) (unsigned int) *language
15463d8817e4Smiod 	      && (re->id.u.id & 0xffff) == re->id.u.id)
15473d8817e4Smiod 	    {
15483d8817e4Smiod 	      fprintf (e, "LANGUAGE %lu, %lu\n",
15493d8817e4Smiod 		       re->id.u.id & ((1 << SUBLANG_SHIFT) - 1),
15503d8817e4Smiod 		       (re->id.u.id >> SUBLANG_SHIFT) & 0xff);
15513d8817e4Smiod 	      *language = re->id.u.id;
15523d8817e4Smiod 	    }
15533d8817e4Smiod 	  break;
15543d8817e4Smiod 
15553d8817e4Smiod 	default:
15563d8817e4Smiod 	  break;
15573d8817e4Smiod 	}
15583d8817e4Smiod 
15593d8817e4Smiod       if (re->subdir)
15603d8817e4Smiod 	write_rc_subdir (e, re, type, name, language, level);
15613d8817e4Smiod       else
15623d8817e4Smiod 	{
15633d8817e4Smiod 	  if (level == 3)
15643d8817e4Smiod 	    {
15653d8817e4Smiod 	      /* This is the normal case: the three levels are
15663d8817e4Smiod                  TYPE/NAME/LANGUAGE.  NAME will have been set at level
15673d8817e4Smiod                  2, and represents the name to use.  We probably just
15683d8817e4Smiod                  set LANGUAGE, and it will probably match what the
15693d8817e4Smiod                  resource itself records if anything.  */
15703d8817e4Smiod 	      write_rc_resource (e, type, name, re->u.res, language);
15713d8817e4Smiod 	    }
15723d8817e4Smiod 	  else
15733d8817e4Smiod 	    {
15743d8817e4Smiod 	      fprintf (e, "// Resource at unexpected level %d\n", level);
15753d8817e4Smiod 	      write_rc_resource (e, type, (struct res_id *) NULL, re->u.res,
15763d8817e4Smiod 				 language);
15773d8817e4Smiod 	    }
15783d8817e4Smiod 	}
15793d8817e4Smiod     }
15803d8817e4Smiod }
15813d8817e4Smiod 
15823d8817e4Smiod /* Write out a subdirectory entry.  E is the file to write to.  RE is
15833d8817e4Smiod    the subdirectory entry.  TYPE and NAME are pointers to higher level
15843d8817e4Smiod    IDs, or NULL.  LANGUAGE is a pointer to the current language.
15853d8817e4Smiod    LEVEL is the level in the tree.  */
15863d8817e4Smiod 
15873d8817e4Smiod static void
write_rc_subdir(FILE * e,const struct res_entry * re,const struct res_id * type,const struct res_id * name,int * language,int level)15883d8817e4Smiod write_rc_subdir (FILE *e, const struct res_entry *re,
15893d8817e4Smiod 		 const struct res_id *type, const struct res_id *name,
15903d8817e4Smiod 		 int *language, int level)
15913d8817e4Smiod {
15923d8817e4Smiod   fprintf (e, "\n");
15933d8817e4Smiod   switch (level)
15943d8817e4Smiod     {
15953d8817e4Smiod     case 1:
15963d8817e4Smiod       fprintf (e, "// Type: ");
15973d8817e4Smiod       if (re->id.named)
15983d8817e4Smiod 	res_id_print (e, re->id, 1);
15993d8817e4Smiod       else
16003d8817e4Smiod 	{
16013d8817e4Smiod 	  const char *s;
16023d8817e4Smiod 
16033d8817e4Smiod 	  switch (re->id.u.id)
16043d8817e4Smiod 	    {
16053d8817e4Smiod 	    case RT_CURSOR: s = "cursor"; break;
16063d8817e4Smiod 	    case RT_BITMAP: s = "bitmap"; break;
16073d8817e4Smiod 	    case RT_ICON: s = "icon"; break;
16083d8817e4Smiod 	    case RT_MENU: s = "menu"; break;
16093d8817e4Smiod 	    case RT_DIALOG: s = "dialog"; break;
16103d8817e4Smiod 	    case RT_STRING: s = "stringtable"; break;
16113d8817e4Smiod 	    case RT_FONTDIR: s = "fontdir"; break;
16123d8817e4Smiod 	    case RT_FONT: s = "font"; break;
16133d8817e4Smiod 	    case RT_ACCELERATOR: s = "accelerators"; break;
16143d8817e4Smiod 	    case RT_RCDATA: s = "rcdata"; break;
16153d8817e4Smiod 	    case RT_MESSAGETABLE: s = "messagetable"; break;
16163d8817e4Smiod 	    case RT_GROUP_CURSOR: s = "group cursor"; break;
16173d8817e4Smiod 	    case RT_GROUP_ICON: s = "group icon"; break;
16183d8817e4Smiod 	    case RT_VERSION: s = "version"; break;
16193d8817e4Smiod 	    case RT_DLGINCLUDE: s = "dlginclude"; break;
16203d8817e4Smiod 	    case RT_PLUGPLAY: s = "plugplay"; break;
16213d8817e4Smiod 	    case RT_VXD: s = "vxd"; break;
16223d8817e4Smiod 	    case RT_ANICURSOR: s = "anicursor"; break;
16233d8817e4Smiod 	    case RT_ANIICON: s = "aniicon"; break;
16243d8817e4Smiod 	    default: s = NULL; break;
16253d8817e4Smiod 	    }
16263d8817e4Smiod 
16273d8817e4Smiod 	  if (s != NULL)
16283d8817e4Smiod 	    fprintf (e, "%s", s);
16293d8817e4Smiod 	  else
16303d8817e4Smiod 	    res_id_print (e, re->id, 1);
16313d8817e4Smiod 	}
16323d8817e4Smiod       fprintf (e, "\n");
16333d8817e4Smiod       break;
16343d8817e4Smiod 
16353d8817e4Smiod     case 2:
16363d8817e4Smiod       fprintf (e, "// Name: ");
16373d8817e4Smiod       res_id_print (e, re->id, 1);
16383d8817e4Smiod       fprintf (e, "\n");
16393d8817e4Smiod       break;
16403d8817e4Smiod 
16413d8817e4Smiod     case 3:
16423d8817e4Smiod       fprintf (e, "// Language: ");
16433d8817e4Smiod       res_id_print (e, re->id, 1);
16443d8817e4Smiod       fprintf (e, "\n");
16453d8817e4Smiod       break;
16463d8817e4Smiod 
16473d8817e4Smiod     default:
16483d8817e4Smiod       fprintf (e, "// Level %d: ", level);
16493d8817e4Smiod       res_id_print (e, re->id, 1);
16503d8817e4Smiod       fprintf (e, "\n");
16513d8817e4Smiod     }
16523d8817e4Smiod 
16533d8817e4Smiod   write_rc_directory (e, re->u.dir, type, name, language, level + 1);
16543d8817e4Smiod }
16553d8817e4Smiod 
16563d8817e4Smiod /* Write out a single resource.  E is the file to write to.  TYPE is a
16573d8817e4Smiod    pointer to the type of the resource.  NAME is a pointer to the name
16583d8817e4Smiod    of the resource; it will be NULL if there is a level mismatch.  RES
16593d8817e4Smiod    is the resource data.  LANGUAGE is a pointer to the current
16603d8817e4Smiod    language.  */
16613d8817e4Smiod 
16623d8817e4Smiod static void
write_rc_resource(FILE * e,const struct res_id * type,const struct res_id * name,const struct res_resource * res,int * language)16633d8817e4Smiod write_rc_resource (FILE *e, const struct res_id *type,
16643d8817e4Smiod 		   const struct res_id *name, const struct res_resource *res,
16653d8817e4Smiod 		   int *language)
16663d8817e4Smiod {
16673d8817e4Smiod   const char *s;
16683d8817e4Smiod   int rt;
16693d8817e4Smiod   int menuex = 0;
16703d8817e4Smiod 
16713d8817e4Smiod   fprintf (e, "\n");
16723d8817e4Smiod 
16733d8817e4Smiod   switch (res->type)
16743d8817e4Smiod     {
16753d8817e4Smiod     default:
16763d8817e4Smiod       abort ();
16773d8817e4Smiod 
16783d8817e4Smiod     case RES_TYPE_ACCELERATOR:
16793d8817e4Smiod       s = "ACCELERATOR";
16803d8817e4Smiod       rt = RT_ACCELERATOR;
16813d8817e4Smiod       break;
16823d8817e4Smiod 
16833d8817e4Smiod     case RES_TYPE_BITMAP:
16843d8817e4Smiod       s = "BITMAP";
16853d8817e4Smiod       rt = RT_BITMAP;
16863d8817e4Smiod       break;
16873d8817e4Smiod 
16883d8817e4Smiod     case RES_TYPE_CURSOR:
16893d8817e4Smiod       s = "CURSOR";
16903d8817e4Smiod       rt = RT_CURSOR;
16913d8817e4Smiod       break;
16923d8817e4Smiod 
16933d8817e4Smiod     case RES_TYPE_GROUP_CURSOR:
16943d8817e4Smiod       s = "GROUP_CURSOR";
16953d8817e4Smiod       rt = RT_GROUP_CURSOR;
16963d8817e4Smiod       break;
16973d8817e4Smiod 
16983d8817e4Smiod     case RES_TYPE_DIALOG:
16993d8817e4Smiod       if (extended_dialog (res->u.dialog))
17003d8817e4Smiod 	s = "DIALOGEX";
17013d8817e4Smiod       else
17023d8817e4Smiod 	s = "DIALOG";
17033d8817e4Smiod       rt = RT_DIALOG;
17043d8817e4Smiod       break;
17053d8817e4Smiod 
17063d8817e4Smiod     case RES_TYPE_FONT:
17073d8817e4Smiod       s = "FONT";
17083d8817e4Smiod       rt = RT_FONT;
17093d8817e4Smiod       break;
17103d8817e4Smiod 
17113d8817e4Smiod     case RES_TYPE_FONTDIR:
17123d8817e4Smiod       s = "FONTDIR";
17133d8817e4Smiod       rt = RT_FONTDIR;
17143d8817e4Smiod       break;
17153d8817e4Smiod 
17163d8817e4Smiod     case RES_TYPE_ICON:
17173d8817e4Smiod       s = "ICON";
17183d8817e4Smiod       rt = RT_ICON;
17193d8817e4Smiod       break;
17203d8817e4Smiod 
17213d8817e4Smiod     case RES_TYPE_GROUP_ICON:
17223d8817e4Smiod       s = "GROUP_ICON";
17233d8817e4Smiod       rt = RT_GROUP_ICON;
17243d8817e4Smiod       break;
17253d8817e4Smiod 
17263d8817e4Smiod     case RES_TYPE_MENU:
17273d8817e4Smiod       if (extended_menu (res->u.menu))
17283d8817e4Smiod 	{
17293d8817e4Smiod 	  s = "MENUEX";
17303d8817e4Smiod 	  menuex = 1;
17313d8817e4Smiod 	}
17323d8817e4Smiod       else
17333d8817e4Smiod 	{
17343d8817e4Smiod 	  s = "MENU";
17353d8817e4Smiod 	  menuex = 0;
17363d8817e4Smiod 	}
17373d8817e4Smiod       rt = RT_MENU;
17383d8817e4Smiod       break;
17393d8817e4Smiod 
17403d8817e4Smiod     case RES_TYPE_MESSAGETABLE:
17413d8817e4Smiod       s = "MESSAGETABLE";
17423d8817e4Smiod       rt = RT_MESSAGETABLE;
17433d8817e4Smiod       break;
17443d8817e4Smiod 
17453d8817e4Smiod     case RES_TYPE_RCDATA:
17463d8817e4Smiod       s = "RCDATA";
17473d8817e4Smiod       rt = RT_RCDATA;
17483d8817e4Smiod       break;
17493d8817e4Smiod 
17503d8817e4Smiod     case RES_TYPE_STRINGTABLE:
17513d8817e4Smiod       s = "STRINGTABLE";
17523d8817e4Smiod       rt = RT_STRING;
17533d8817e4Smiod       break;
17543d8817e4Smiod 
17553d8817e4Smiod     case RES_TYPE_USERDATA:
17563d8817e4Smiod       s = NULL;
17573d8817e4Smiod       rt = 0;
17583d8817e4Smiod       break;
17593d8817e4Smiod 
17603d8817e4Smiod     case RES_TYPE_VERSIONINFO:
17613d8817e4Smiod       s = "VERSIONINFO";
17623d8817e4Smiod       rt = RT_VERSION;
17633d8817e4Smiod       break;
17643d8817e4Smiod     }
17653d8817e4Smiod 
17663d8817e4Smiod   if (rt != 0
17673d8817e4Smiod       && type != NULL
17683d8817e4Smiod       && (type->named || type->u.id != (unsigned long) rt))
17693d8817e4Smiod     {
17703d8817e4Smiod       fprintf (e, "// Unexpected resource type mismatch: ");
17713d8817e4Smiod       res_id_print (e, *type, 1);
17723d8817e4Smiod       fprintf (e, " != %d", rt);
17733d8817e4Smiod     }
17743d8817e4Smiod 
17753d8817e4Smiod   if (res->coff_info.codepage != 0)
17763d8817e4Smiod     fprintf (e, "// Code page: %lu\n", res->coff_info.codepage);
17773d8817e4Smiod   if (res->coff_info.reserved != 0)
17783d8817e4Smiod     fprintf (e, "// COFF reserved value: %lu\n", res->coff_info.reserved);
17793d8817e4Smiod 
17803d8817e4Smiod   if (name != NULL)
17813d8817e4Smiod     res_id_print (e, *name, 0);
17823d8817e4Smiod   else
17833d8817e4Smiod     fprintf (e, "??Unknown-Name??");
17843d8817e4Smiod 
17853d8817e4Smiod   fprintf (e, " ");
17863d8817e4Smiod   if (s != NULL)
17873d8817e4Smiod     fprintf (e, "%s", s);
17883d8817e4Smiod   else if (type != NULL)
17893d8817e4Smiod     res_id_print (e, *type, 0);
17903d8817e4Smiod   else
17913d8817e4Smiod     fprintf (e, "??Unknown-Type??");
17923d8817e4Smiod 
17933d8817e4Smiod   if (res->res_info.memflags != 0)
17943d8817e4Smiod     {
17953d8817e4Smiod       if ((res->res_info.memflags & MEMFLAG_MOVEABLE) != 0)
17963d8817e4Smiod 	fprintf (e, " MOVEABLE");
17973d8817e4Smiod       if ((res->res_info.memflags & MEMFLAG_PURE) != 0)
17983d8817e4Smiod 	fprintf (e, " PURE");
17993d8817e4Smiod       if ((res->res_info.memflags & MEMFLAG_PRELOAD) != 0)
18003d8817e4Smiod 	fprintf (e, " PRELOAD");
18013d8817e4Smiod       if ((res->res_info.memflags & MEMFLAG_DISCARDABLE) != 0)
18023d8817e4Smiod 	fprintf (e, " DISCARDABLE");
18033d8817e4Smiod     }
18043d8817e4Smiod 
18053d8817e4Smiod   if (res->type == RES_TYPE_DIALOG)
18063d8817e4Smiod     {
18073d8817e4Smiod       fprintf (e, " %d, %d, %d, %d", res->u.dialog->x, res->u.dialog->y,
18083d8817e4Smiod 	       res->u.dialog->width, res->u.dialog->height);
18093d8817e4Smiod       if (res->u.dialog->ex != NULL
18103d8817e4Smiod 	  && res->u.dialog->ex->help != 0)
18113d8817e4Smiod 	fprintf (e, ", %lu", res->u.dialog->ex->help);
18123d8817e4Smiod     }
18133d8817e4Smiod 
18143d8817e4Smiod   fprintf (e, "\n");
18153d8817e4Smiod 
18163d8817e4Smiod   if ((res->res_info.language != 0 && res->res_info.language != *language)
18173d8817e4Smiod       || res->res_info.characteristics != 0
18183d8817e4Smiod       || res->res_info.version != 0)
18193d8817e4Smiod     {
18203d8817e4Smiod       int modifiers;
18213d8817e4Smiod 
18223d8817e4Smiod       switch (res->type)
18233d8817e4Smiod 	{
18243d8817e4Smiod 	case RES_TYPE_ACCELERATOR:
18253d8817e4Smiod 	case RES_TYPE_DIALOG:
18263d8817e4Smiod 	case RES_TYPE_MENU:
18273d8817e4Smiod 	case RES_TYPE_RCDATA:
18283d8817e4Smiod 	case RES_TYPE_STRINGTABLE:
18293d8817e4Smiod 	  modifiers = 1;
18303d8817e4Smiod 	  break;
18313d8817e4Smiod 
18323d8817e4Smiod 	default:
18333d8817e4Smiod 	  modifiers = 0;
18343d8817e4Smiod 	  break;
18353d8817e4Smiod 	}
18363d8817e4Smiod 
18373d8817e4Smiod       if (res->res_info.language != 0 && res->res_info.language != *language)
18383d8817e4Smiod 	fprintf (e, "%sLANGUAGE %d, %d\n",
18393d8817e4Smiod 		 modifiers ? "// " : "",
18403d8817e4Smiod 		 res->res_info.language & ((1<<SUBLANG_SHIFT)-1),
18413d8817e4Smiod 		 (res->res_info.language >> SUBLANG_SHIFT) & 0xff);
18423d8817e4Smiod       if (res->res_info.characteristics != 0)
18433d8817e4Smiod 	fprintf (e, "%sCHARACTERISTICS %lu\n",
18443d8817e4Smiod 		 modifiers ? "// " : "",
18453d8817e4Smiod 		 res->res_info.characteristics);
18463d8817e4Smiod       if (res->res_info.version != 0)
18473d8817e4Smiod 	fprintf (e, "%sVERSION %lu\n",
18483d8817e4Smiod 		 modifiers ? "// " : "",
18493d8817e4Smiod 		 res->res_info.version);
18503d8817e4Smiod     }
18513d8817e4Smiod 
18523d8817e4Smiod   switch (res->type)
18533d8817e4Smiod     {
18543d8817e4Smiod     default:
18553d8817e4Smiod       abort ();
18563d8817e4Smiod 
18573d8817e4Smiod     case RES_TYPE_ACCELERATOR:
18583d8817e4Smiod       write_rc_accelerators (e, res->u.acc);
18593d8817e4Smiod       break;
18603d8817e4Smiod 
18613d8817e4Smiod     case RES_TYPE_CURSOR:
18623d8817e4Smiod       write_rc_cursor (e, res->u.cursor);
18633d8817e4Smiod       break;
18643d8817e4Smiod 
18653d8817e4Smiod     case RES_TYPE_GROUP_CURSOR:
18663d8817e4Smiod       write_rc_group_cursor (e, res->u.group_cursor);
18673d8817e4Smiod       break;
18683d8817e4Smiod 
18693d8817e4Smiod     case RES_TYPE_DIALOG:
18703d8817e4Smiod       write_rc_dialog (e, res->u.dialog);
18713d8817e4Smiod       break;
18723d8817e4Smiod 
18733d8817e4Smiod     case RES_TYPE_FONTDIR:
18743d8817e4Smiod       write_rc_fontdir (e, res->u.fontdir);
18753d8817e4Smiod       break;
18763d8817e4Smiod 
18773d8817e4Smiod     case RES_TYPE_GROUP_ICON:
18783d8817e4Smiod       write_rc_group_icon (e, res->u.group_icon);
18793d8817e4Smiod       break;
18803d8817e4Smiod 
18813d8817e4Smiod     case RES_TYPE_MENU:
18823d8817e4Smiod       write_rc_menu (e, res->u.menu, menuex);
18833d8817e4Smiod       break;
18843d8817e4Smiod 
18853d8817e4Smiod     case RES_TYPE_RCDATA:
18863d8817e4Smiod       write_rc_rcdata (e, res->u.rcdata, 0);
18873d8817e4Smiod       break;
18883d8817e4Smiod 
18893d8817e4Smiod     case RES_TYPE_STRINGTABLE:
18903d8817e4Smiod       write_rc_stringtable (e, name, res->u.stringtable);
18913d8817e4Smiod       break;
18923d8817e4Smiod 
18933d8817e4Smiod     case RES_TYPE_USERDATA:
18943d8817e4Smiod       write_rc_rcdata (e, res->u.userdata, 0);
18953d8817e4Smiod       break;
18963d8817e4Smiod 
18973d8817e4Smiod     case RES_TYPE_VERSIONINFO:
18983d8817e4Smiod       write_rc_versioninfo (e, res->u.versioninfo);
18993d8817e4Smiod       break;
19003d8817e4Smiod 
19013d8817e4Smiod     case RES_TYPE_BITMAP:
19023d8817e4Smiod     case RES_TYPE_FONT:
19033d8817e4Smiod     case RES_TYPE_ICON:
19043d8817e4Smiod     case RES_TYPE_MESSAGETABLE:
19053d8817e4Smiod       write_rc_filedata (e, res->u.data.length, res->u.data.data);
19063d8817e4Smiod       break;
19073d8817e4Smiod     }
19083d8817e4Smiod }
19093d8817e4Smiod 
19103d8817e4Smiod /* Write out accelerator information.  */
19113d8817e4Smiod 
19123d8817e4Smiod static void
write_rc_accelerators(FILE * e,const struct accelerator * accelerators)19133d8817e4Smiod write_rc_accelerators (FILE *e, const struct accelerator *accelerators)
19143d8817e4Smiod {
19153d8817e4Smiod   const struct accelerator *acc;
19163d8817e4Smiod 
19173d8817e4Smiod   fprintf (e, "BEGIN\n");
19183d8817e4Smiod   for (acc = accelerators; acc != NULL; acc = acc->next)
19193d8817e4Smiod     {
19203d8817e4Smiod       int printable;
19213d8817e4Smiod 
19223d8817e4Smiod       fprintf (e, "  ");
19233d8817e4Smiod 
19243d8817e4Smiod       if ((acc->key & 0x7f) == acc->key
19253d8817e4Smiod 	  && ISPRINT (acc->key)
19263d8817e4Smiod 	  && (acc->flags & ACC_VIRTKEY) == 0)
19273d8817e4Smiod 	{
19283d8817e4Smiod 	  fprintf (e, "\"%c\"", acc->key);
19293d8817e4Smiod 	  printable = 1;
19303d8817e4Smiod 	}
19313d8817e4Smiod       else
19323d8817e4Smiod 	{
19333d8817e4Smiod 	  fprintf (e, "%d", acc->key);
19343d8817e4Smiod 	  printable = 0;
19353d8817e4Smiod 	}
19363d8817e4Smiod 
19373d8817e4Smiod       fprintf (e, ", %d", acc->id);
19383d8817e4Smiod 
19393d8817e4Smiod       if (! printable)
19403d8817e4Smiod 	{
19413d8817e4Smiod 	  if ((acc->flags & ACC_VIRTKEY) != 0)
19423d8817e4Smiod 	    fprintf (e, ", VIRTKEY");
19433d8817e4Smiod 	  else
19443d8817e4Smiod 	    fprintf (e, ", ASCII");
19453d8817e4Smiod 	}
19463d8817e4Smiod 
19473d8817e4Smiod       if ((acc->flags & ACC_SHIFT) != 0)
19483d8817e4Smiod 	fprintf (e, ", SHIFT");
19493d8817e4Smiod       if ((acc->flags & ACC_CONTROL) != 0)
19503d8817e4Smiod 	fprintf (e, ", CONTROL");
19513d8817e4Smiod       if ((acc->flags & ACC_ALT) != 0)
19523d8817e4Smiod 	fprintf (e, ", ALT");
19533d8817e4Smiod 
19543d8817e4Smiod       fprintf (e, "\n");
19553d8817e4Smiod     }
19563d8817e4Smiod 
19573d8817e4Smiod   fprintf (e, "END\n");
19583d8817e4Smiod }
19593d8817e4Smiod 
19603d8817e4Smiod /* Write out cursor information.  This would normally be in a separate
19613d8817e4Smiod    file, which the rc file would include.  */
19623d8817e4Smiod 
19633d8817e4Smiod static void
write_rc_cursor(FILE * e,const struct cursor * cursor)19643d8817e4Smiod write_rc_cursor (FILE *e, const struct cursor *cursor)
19653d8817e4Smiod {
19663d8817e4Smiod   fprintf (e, "// Hotspot: x: %d; y: %d\n", cursor->xhotspot,
19673d8817e4Smiod 	   cursor->yhotspot);
19683d8817e4Smiod   write_rc_filedata (e, cursor->length, cursor->data);
19693d8817e4Smiod }
19703d8817e4Smiod 
19713d8817e4Smiod /* Write out group cursor data.  This would normally be built from the
19723d8817e4Smiod    cursor data.  */
19733d8817e4Smiod 
19743d8817e4Smiod static void
write_rc_group_cursor(FILE * e,const struct group_cursor * group_cursor)19753d8817e4Smiod write_rc_group_cursor (FILE *e, const struct group_cursor *group_cursor)
19763d8817e4Smiod {
19773d8817e4Smiod   const struct group_cursor *gc;
19783d8817e4Smiod 
19793d8817e4Smiod   for (gc = group_cursor; gc != NULL; gc = gc->next)
19803d8817e4Smiod     {
19813d8817e4Smiod       fprintf (e, "// width: %d; height %d; planes %d; bits %d\n",
19823d8817e4Smiod 	     gc->width, gc->height, gc->planes, gc->bits);
19833d8817e4Smiod       fprintf (e, "// data bytes: %lu; index: %d\n",
19843d8817e4Smiod 	       gc->bytes, gc->index);
19853d8817e4Smiod     }
19863d8817e4Smiod }
19873d8817e4Smiod 
19883d8817e4Smiod /* Write dialog data.  */
19893d8817e4Smiod 
19903d8817e4Smiod static void
write_rc_dialog(FILE * e,const struct dialog * dialog)19913d8817e4Smiod write_rc_dialog (FILE *e, const struct dialog *dialog)
19923d8817e4Smiod {
19933d8817e4Smiod   const struct dialog_control *control;
19943d8817e4Smiod 
19953d8817e4Smiod   fprintf (e, "STYLE 0x%lx\n", dialog->style);
19963d8817e4Smiod 
19973d8817e4Smiod   if (dialog->exstyle != 0)
19983d8817e4Smiod     fprintf (e, "EXSTYLE 0x%lx\n", dialog->exstyle);
19993d8817e4Smiod 
20003d8817e4Smiod   if ((dialog->class.named && dialog->class.u.n.length > 0)
20013d8817e4Smiod       || dialog->class.u.id != 0)
20023d8817e4Smiod     {
20033d8817e4Smiod       fprintf (e, "CLASS ");
20043d8817e4Smiod       res_id_print (e, dialog->class, 1);
20053d8817e4Smiod       fprintf (e, "\n");
20063d8817e4Smiod     }
20073d8817e4Smiod 
20083d8817e4Smiod   if (dialog->caption != NULL)
20093d8817e4Smiod     {
20103d8817e4Smiod       fprintf (e, "CAPTION \"");
20113d8817e4Smiod       unicode_print (e, dialog->caption, -1);
20123d8817e4Smiod       fprintf (e, "\"\n");
20133d8817e4Smiod     }
20143d8817e4Smiod 
20153d8817e4Smiod   if ((dialog->menu.named && dialog->menu.u.n.length > 0)
20163d8817e4Smiod       || dialog->menu.u.id != 0)
20173d8817e4Smiod     {
20183d8817e4Smiod       fprintf (e, "MENU ");
20193d8817e4Smiod       res_id_print (e, dialog->menu, 0);
20203d8817e4Smiod       fprintf (e, "\n");
20213d8817e4Smiod     }
20223d8817e4Smiod 
20233d8817e4Smiod   if (dialog->font != NULL)
20243d8817e4Smiod     {
20253d8817e4Smiod       fprintf (e, "FONT %d, \"", dialog->pointsize);
20263d8817e4Smiod       unicode_print (e, dialog->font, -1);
20273d8817e4Smiod       fprintf (e, "\"");
20283d8817e4Smiod       if (dialog->ex != NULL
20293d8817e4Smiod 	  && (dialog->ex->weight != 0
20303d8817e4Smiod 	      || dialog->ex->italic != 0
20313d8817e4Smiod 	      || dialog->ex->charset != 1))
20323d8817e4Smiod 	fprintf (e, ", %d, %d, %d",
20333d8817e4Smiod 		 dialog->ex->weight, dialog->ex->italic, dialog->ex->charset);
20343d8817e4Smiod       fprintf (e, "\n");
20353d8817e4Smiod     }
20363d8817e4Smiod 
20373d8817e4Smiod   fprintf (e, "BEGIN\n");
20383d8817e4Smiod 
20393d8817e4Smiod   for (control = dialog->controls; control != NULL; control = control->next)
20403d8817e4Smiod     write_rc_dialog_control (e, control);
20413d8817e4Smiod 
20423d8817e4Smiod   fprintf (e, "END\n");
20433d8817e4Smiod }
20443d8817e4Smiod 
20453d8817e4Smiod /* For each predefined control keyword, this table provides the class
20463d8817e4Smiod    and the style.  */
20473d8817e4Smiod 
20483d8817e4Smiod struct control_info
20493d8817e4Smiod {
20503d8817e4Smiod   const char *name;
20513d8817e4Smiod   unsigned short class;
20523d8817e4Smiod   unsigned long style;
20533d8817e4Smiod };
20543d8817e4Smiod 
20553d8817e4Smiod static const struct control_info control_info[] =
20563d8817e4Smiod {
20573d8817e4Smiod   { "AUTO3STATE", CTL_BUTTON, BS_AUTO3STATE },
20583d8817e4Smiod   { "AUTOCHECKBOX", CTL_BUTTON, BS_AUTOCHECKBOX },
20593d8817e4Smiod   { "AUTORADIOBUTTON", CTL_BUTTON, BS_AUTORADIOBUTTON },
20603d8817e4Smiod   { "CHECKBOX", CTL_BUTTON, BS_CHECKBOX },
20613d8817e4Smiod   { "COMBOBOX", CTL_COMBOBOX, (unsigned long) -1 },
20623d8817e4Smiod   { "CTEXT", CTL_STATIC, SS_CENTER },
20633d8817e4Smiod   { "DEFPUSHBUTTON", CTL_BUTTON, BS_DEFPUSHBUTTON },
20643d8817e4Smiod   { "EDITTEXT", CTL_EDIT, (unsigned long) -1 },
20653d8817e4Smiod   { "GROUPBOX", CTL_BUTTON, BS_GROUPBOX },
20663d8817e4Smiod   { "ICON", CTL_STATIC, SS_ICON },
20673d8817e4Smiod   { "LISTBOX", CTL_LISTBOX, (unsigned long) -1 },
20683d8817e4Smiod   { "LTEXT", CTL_STATIC, SS_LEFT },
20693d8817e4Smiod   { "PUSHBOX", CTL_BUTTON, BS_PUSHBOX },
20703d8817e4Smiod   { "PUSHBUTTON", CTL_BUTTON, BS_PUSHBUTTON },
20713d8817e4Smiod   { "RADIOBUTTON", CTL_BUTTON, BS_RADIOBUTTON },
20723d8817e4Smiod   { "RTEXT", CTL_STATIC, SS_RIGHT },
20733d8817e4Smiod   { "SCROLLBAR", CTL_SCROLLBAR, (unsigned long) -1 },
20743d8817e4Smiod   { "STATE3", CTL_BUTTON, BS_3STATE },
20753d8817e4Smiod   /* It's important that USERBUTTON come after all the other button
20763d8817e4Smiod      types, so that it won't be matched too early.  */
20773d8817e4Smiod   { "USERBUTTON", CTL_BUTTON, (unsigned long) -1 },
20783d8817e4Smiod   { NULL, 0, 0 }
20793d8817e4Smiod };
20803d8817e4Smiod 
20813d8817e4Smiod /* Write a dialog control.  */
20823d8817e4Smiod 
20833d8817e4Smiod static void
write_rc_dialog_control(FILE * e,const struct dialog_control * control)20843d8817e4Smiod write_rc_dialog_control (FILE *e, const struct dialog_control *control)
20853d8817e4Smiod {
20863d8817e4Smiod   const struct control_info *ci;
20873d8817e4Smiod 
20883d8817e4Smiod   fprintf (e, "  ");
20893d8817e4Smiod 
20903d8817e4Smiod   if (control->class.named)
20913d8817e4Smiod     ci = NULL;
20923d8817e4Smiod   else
20933d8817e4Smiod     {
20943d8817e4Smiod       for (ci = control_info; ci->name != NULL; ++ci)
20953d8817e4Smiod 	if (ci->class == control->class.u.id
20963d8817e4Smiod 	    && (ci->style == (unsigned long) -1
20973d8817e4Smiod 		|| ci->style == (control->style & 0xff)))
20983d8817e4Smiod 	  break;
20993d8817e4Smiod     }
21003d8817e4Smiod   if (ci == NULL)
21013d8817e4Smiod     fprintf (e, "CONTROL");
21023d8817e4Smiod   else if (ci->name != NULL)
21033d8817e4Smiod     fprintf (e, "%s", ci->name);
21043d8817e4Smiod   else
21053d8817e4Smiod     fprintf (e, "CONTROL");
21063d8817e4Smiod 
21073d8817e4Smiod   if (control->text.named || control->text.u.id != 0)
21083d8817e4Smiod     {
21093d8817e4Smiod       fprintf (e, " ");
21103d8817e4Smiod       res_id_print (e, control->text, 1);
21113d8817e4Smiod       fprintf (e, ",");
21123d8817e4Smiod     }
21133d8817e4Smiod 
21143d8817e4Smiod   fprintf (e, " %d, ", control->id);
21153d8817e4Smiod 
21163d8817e4Smiod   if (ci == NULL)
21173d8817e4Smiod     {
21183d8817e4Smiod       if (control->class.named)
21193d8817e4Smiod 	fprintf (e, "\"");
21203d8817e4Smiod       res_id_print (e, control->class, 0);
21213d8817e4Smiod       if (control->class.named)
21223d8817e4Smiod 	fprintf (e, "\"");
21233d8817e4Smiod       fprintf (e, ", 0x%lx, ", control->style);
21243d8817e4Smiod     }
21253d8817e4Smiod 
21263d8817e4Smiod   fprintf (e, "%d, %d", control->x, control->y);
21273d8817e4Smiod 
21283d8817e4Smiod   if (control->style != SS_ICON
21293d8817e4Smiod       || control->exstyle != 0
21303d8817e4Smiod       || control->width != 0
21313d8817e4Smiod       || control->height != 0
21323d8817e4Smiod       || control->help != 0)
21333d8817e4Smiod     {
21343d8817e4Smiod       fprintf (e, ", %d, %d", control->width, control->height);
21353d8817e4Smiod 
21363d8817e4Smiod       /* FIXME: We don't need to print the style if it is the default.
21373d8817e4Smiod 	 More importantly, in certain cases we actually need to turn
21383d8817e4Smiod 	 off parts of the forced style, by using NOT.  */
21393d8817e4Smiod       fprintf (e, ", 0x%lx", control->style);
21403d8817e4Smiod 
21413d8817e4Smiod       if (control->exstyle != 0 || control->help != 0)
21423d8817e4Smiod 	fprintf (e, ", 0x%lx, %lu", control->exstyle, control->help);
21433d8817e4Smiod     }
21443d8817e4Smiod 
21453d8817e4Smiod   fprintf (e, "\n");
21463d8817e4Smiod 
21473d8817e4Smiod   if (control->data != NULL)
21483d8817e4Smiod     write_rc_rcdata (e, control->data, 2);
21493d8817e4Smiod }
21503d8817e4Smiod 
21513d8817e4Smiod /* Write out font directory data.  This would normally be built from
21523d8817e4Smiod    the font data.  */
21533d8817e4Smiod 
21543d8817e4Smiod static void
write_rc_fontdir(FILE * e,const struct fontdir * fontdir)21553d8817e4Smiod write_rc_fontdir (FILE *e, const struct fontdir *fontdir)
21563d8817e4Smiod {
21573d8817e4Smiod   const struct fontdir *fc;
21583d8817e4Smiod 
21593d8817e4Smiod   for (fc = fontdir; fc != NULL; fc = fc->next)
21603d8817e4Smiod     {
21613d8817e4Smiod       fprintf (e, "// Font index: %d\n", fc->index);
21623d8817e4Smiod       write_rc_filedata (e, fc->length, fc->data);
21633d8817e4Smiod     }
21643d8817e4Smiod }
21653d8817e4Smiod 
21663d8817e4Smiod /* Write out group icon data.  This would normally be built from the
21673d8817e4Smiod    icon data.  */
21683d8817e4Smiod 
21693d8817e4Smiod static void
write_rc_group_icon(FILE * e,const struct group_icon * group_icon)21703d8817e4Smiod write_rc_group_icon (FILE *e, const struct group_icon *group_icon)
21713d8817e4Smiod {
21723d8817e4Smiod   const struct group_icon *gi;
21733d8817e4Smiod 
21743d8817e4Smiod   for (gi = group_icon; gi != NULL; gi = gi->next)
21753d8817e4Smiod     {
21763d8817e4Smiod       fprintf (e, "// width: %d; height %d; colors: %d; planes %d; bits %d\n",
21773d8817e4Smiod 	       gi->width, gi->height, gi->colors, gi->planes, gi->bits);
21783d8817e4Smiod       fprintf (e, "// data bytes: %lu; index: %d\n",
21793d8817e4Smiod 	       gi->bytes, gi->index);
21803d8817e4Smiod     }
21813d8817e4Smiod }
21823d8817e4Smiod 
21833d8817e4Smiod /* Write out a menu resource.  */
21843d8817e4Smiod 
21853d8817e4Smiod static void
write_rc_menu(FILE * e,const struct menu * menu,int menuex)21863d8817e4Smiod write_rc_menu (FILE *e, const struct menu *menu, int menuex)
21873d8817e4Smiod {
21883d8817e4Smiod   if (menu->help != 0)
21893d8817e4Smiod     fprintf (e, "// Help ID: %lu\n", menu->help);
21903d8817e4Smiod   write_rc_menuitems (e, menu->items, menuex, 0);
21913d8817e4Smiod }
21923d8817e4Smiod 
21933d8817e4Smiod /* Write out menuitems.  */
21943d8817e4Smiod 
21953d8817e4Smiod static void
write_rc_menuitems(FILE * e,const struct menuitem * menuitems,int menuex,int ind)21963d8817e4Smiod write_rc_menuitems (FILE *e, const struct menuitem *menuitems, int menuex,
21973d8817e4Smiod 		    int ind)
21983d8817e4Smiod {
21993d8817e4Smiod   const struct menuitem *mi;
22003d8817e4Smiod 
22013d8817e4Smiod   indent (e, ind);
22023d8817e4Smiod   fprintf (e, "BEGIN\n");
22033d8817e4Smiod 
22043d8817e4Smiod   for (mi = menuitems; mi != NULL; mi = mi->next)
22053d8817e4Smiod     {
22063d8817e4Smiod       indent (e, ind + 2);
22073d8817e4Smiod 
22083d8817e4Smiod       if (mi->popup == NULL)
22093d8817e4Smiod 	fprintf (e, "MENUITEM");
22103d8817e4Smiod       else
22113d8817e4Smiod 	fprintf (e, "POPUP");
22123d8817e4Smiod 
22133d8817e4Smiod       if (! menuex
22143d8817e4Smiod 	  && mi->popup == NULL
22153d8817e4Smiod 	  && mi->text == NULL
22163d8817e4Smiod 	  && mi->type == 0
22173d8817e4Smiod 	  && mi->id == 0)
22183d8817e4Smiod 	{
22193d8817e4Smiod 	  fprintf (e, " SEPARATOR\n");
22203d8817e4Smiod 	  continue;
22213d8817e4Smiod 	}
22223d8817e4Smiod 
22233d8817e4Smiod       if (mi->text == NULL)
22243d8817e4Smiod 	fprintf (e, " \"\"");
22253d8817e4Smiod       else
22263d8817e4Smiod 	{
22273d8817e4Smiod 	  fprintf (e, " \"");
22283d8817e4Smiod 	  unicode_print (e, mi->text, -1);
22293d8817e4Smiod 	  fprintf (e, "\"");
22303d8817e4Smiod 	}
22313d8817e4Smiod 
22323d8817e4Smiod       if (! menuex)
22333d8817e4Smiod 	{
22343d8817e4Smiod 	  if (mi->popup == NULL)
22353d8817e4Smiod 	    fprintf (e, ", %d", mi->id);
22363d8817e4Smiod 
22373d8817e4Smiod 	  if ((mi->type & MENUITEM_CHECKED) != 0)
22383d8817e4Smiod 	    fprintf (e, ", CHECKED");
22393d8817e4Smiod 	  if ((mi->type & MENUITEM_GRAYED) != 0)
22403d8817e4Smiod 	    fprintf (e, ", GRAYED");
22413d8817e4Smiod 	  if ((mi->type & MENUITEM_HELP) != 0)
22423d8817e4Smiod 	    fprintf (e, ", HELP");
22433d8817e4Smiod 	  if ((mi->type & MENUITEM_INACTIVE) != 0)
22443d8817e4Smiod 	    fprintf (e, ", INACTIVE");
22453d8817e4Smiod 	  if ((mi->type & MENUITEM_MENUBARBREAK) != 0)
22463d8817e4Smiod 	    fprintf (e, ", MENUBARBREAK");
22473d8817e4Smiod 	  if ((mi->type & MENUITEM_MENUBREAK) != 0)
22483d8817e4Smiod 	    fprintf (e, ", MENUBREAK");
22493d8817e4Smiod 	}
22503d8817e4Smiod       else
22513d8817e4Smiod 	{
22523d8817e4Smiod 	  if (mi->id != 0 || mi->type != 0 || mi->state != 0 || mi->help != 0)
22533d8817e4Smiod 	    {
22543d8817e4Smiod 	      fprintf (e, ", %d", mi->id);
22553d8817e4Smiod 	      if (mi->type != 0 || mi->state != 0 || mi->help != 0)
22563d8817e4Smiod 		{
22573d8817e4Smiod 		  fprintf (e, ", %lu", mi->type);
22583d8817e4Smiod 		  if (mi->state != 0 || mi->help != 0)
22593d8817e4Smiod 		    {
22603d8817e4Smiod 		      fprintf (e, ", %lu", mi->state);
22613d8817e4Smiod 		      if (mi->help != 0)
22623d8817e4Smiod 			fprintf (e, ", %lu", mi->help);
22633d8817e4Smiod 		    }
22643d8817e4Smiod 		}
22653d8817e4Smiod 	    }
22663d8817e4Smiod 	}
22673d8817e4Smiod 
22683d8817e4Smiod       fprintf (e, "\n");
22693d8817e4Smiod 
22703d8817e4Smiod       if (mi->popup != NULL)
22713d8817e4Smiod 	write_rc_menuitems (e, mi->popup, menuex, ind + 2);
22723d8817e4Smiod     }
22733d8817e4Smiod 
22743d8817e4Smiod   indent (e, ind);
22753d8817e4Smiod   fprintf (e, "END\n");
22763d8817e4Smiod }
22773d8817e4Smiod 
22783d8817e4Smiod /* Write out an rcdata resource.  This is also used for other types of
22793d8817e4Smiod    resources that need to print arbitrary data.  */
22803d8817e4Smiod 
22813d8817e4Smiod static void
write_rc_rcdata(FILE * e,const struct rcdata_item * rcdata,int ind)22823d8817e4Smiod write_rc_rcdata (FILE *e, const struct rcdata_item *rcdata, int ind)
22833d8817e4Smiod {
22843d8817e4Smiod   const struct rcdata_item *ri;
22853d8817e4Smiod 
22863d8817e4Smiod   indent (e, ind);
22873d8817e4Smiod   fprintf (e, "BEGIN\n");
22883d8817e4Smiod 
22893d8817e4Smiod   for (ri = rcdata; ri != NULL; ri = ri->next)
22903d8817e4Smiod     {
22913d8817e4Smiod       if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0)
22923d8817e4Smiod 	continue;
22933d8817e4Smiod 
22943d8817e4Smiod       indent (e, ind + 2);
22953d8817e4Smiod 
22963d8817e4Smiod       switch (ri->type)
22973d8817e4Smiod 	{
22983d8817e4Smiod 	default:
22993d8817e4Smiod 	  abort ();
23003d8817e4Smiod 
23013d8817e4Smiod 	case RCDATA_WORD:
23023d8817e4Smiod 	  fprintf (e, "%d", ri->u.word);
23033d8817e4Smiod 	  break;
23043d8817e4Smiod 
23053d8817e4Smiod 	case RCDATA_DWORD:
23063d8817e4Smiod 	  fprintf (e, "%luL", ri->u.dword);
23073d8817e4Smiod 	  break;
23083d8817e4Smiod 
23093d8817e4Smiod 	case RCDATA_STRING:
23103d8817e4Smiod 	  {
23113d8817e4Smiod 	    const char *s;
23123d8817e4Smiod 	    unsigned long i;
23133d8817e4Smiod 
23143d8817e4Smiod 	    fprintf (e, "\"");
23153d8817e4Smiod 	    s = ri->u.string.s;
23163d8817e4Smiod 	    for (i = 0; i < ri->u.string.length; i++)
23173d8817e4Smiod 	      {
23183d8817e4Smiod 		if (ISPRINT (*s))
23193d8817e4Smiod 		  putc (*s, e);
23203d8817e4Smiod 		else
23213d8817e4Smiod 		  fprintf (e, "\\%03o", *s);
23223d8817e4Smiod 	      }
23233d8817e4Smiod 	    fprintf (e, "\"");
23243d8817e4Smiod 	    break;
23253d8817e4Smiod 	  }
23263d8817e4Smiod 
23273d8817e4Smiod 	case RCDATA_WSTRING:
23283d8817e4Smiod 	  fprintf (e, "L\"");
23293d8817e4Smiod 	  unicode_print (e, ri->u.wstring.w, ri->u.wstring.length);
23303d8817e4Smiod 	  fprintf (e, "\"");
23313d8817e4Smiod 	  break;
23323d8817e4Smiod 
23333d8817e4Smiod 	case RCDATA_BUFFER:
23343d8817e4Smiod 	  {
23353d8817e4Smiod 	    unsigned long i;
23363d8817e4Smiod 	    int first;
23373d8817e4Smiod 
23383d8817e4Smiod 	    /* Assume little endian data.  */
23393d8817e4Smiod 
23403d8817e4Smiod 	    first = 1;
23413d8817e4Smiod 	    for (i = 0; i + 3 < ri->u.buffer.length; i += 4)
23423d8817e4Smiod 	      {
23433d8817e4Smiod 		unsigned long l;
23443d8817e4Smiod 		int j;
23453d8817e4Smiod 
23463d8817e4Smiod 		if (! first)
23473d8817e4Smiod 		  indent (e, ind + 2);
23483d8817e4Smiod 		l = ((((((ri->u.buffer.data[i + 3] << 8)
23493d8817e4Smiod 			 | ri->u.buffer.data[i + 2]) << 8)
23503d8817e4Smiod 		       | ri->u.buffer.data[i + 1]) << 8)
23513d8817e4Smiod 		     | ri->u.buffer.data[i]);
23523d8817e4Smiod 		fprintf (e, "%luL", l);
23533d8817e4Smiod 		if (i + 4 < ri->u.buffer.length || ri->next != NULL)
23543d8817e4Smiod 		  fprintf (e, ",");
23553d8817e4Smiod 		for (j = 0; j < 4; ++j)
23563d8817e4Smiod 		  if (! ISPRINT (ri->u.buffer.data[i + j])
23573d8817e4Smiod 		      && ri->u.buffer.data[i + j] != 0)
23583d8817e4Smiod 		    break;
23593d8817e4Smiod 		if (j >= 4)
23603d8817e4Smiod 		  {
23613d8817e4Smiod 		    fprintf (e, "\t// ");
23623d8817e4Smiod 		    for (j = 0; j < 4; ++j)
23633d8817e4Smiod 		      {
23643d8817e4Smiod 			if (! ISPRINT (ri->u.buffer.data[i + j]))
23653d8817e4Smiod 			  fprintf (e, "\\%03o", ri->u.buffer.data[i + j]);
23663d8817e4Smiod 			else
23673d8817e4Smiod 			  {
23683d8817e4Smiod 			    if (ri->u.buffer.data[i + j] == '\\')
23693d8817e4Smiod 			      fprintf (e, "\\");
23703d8817e4Smiod 			    fprintf (e, "%c", ri->u.buffer.data[i + j]);
23713d8817e4Smiod 			  }
23723d8817e4Smiod 		      }
23733d8817e4Smiod 		  }
23743d8817e4Smiod 		fprintf (e, "\n");
23753d8817e4Smiod 		first = 0;
23763d8817e4Smiod 	      }
23773d8817e4Smiod 
23783d8817e4Smiod 	    if (i + 1 < ri->u.buffer.length)
23793d8817e4Smiod 	      {
23803d8817e4Smiod 		int s;
23813d8817e4Smiod 		int j;
23823d8817e4Smiod 
23833d8817e4Smiod 		if (! first)
23843d8817e4Smiod 		  indent (e, ind + 2);
23853d8817e4Smiod 		s = (ri->u.buffer.data[i + 1] << 8) | ri->u.buffer.data[i];
23863d8817e4Smiod 		fprintf (e, "%d", s);
23873d8817e4Smiod 		if (i + 2 < ri->u.buffer.length || ri->next != NULL)
23883d8817e4Smiod 		  fprintf (e, ",");
23893d8817e4Smiod 		for (j = 0; j < 2; ++j)
23903d8817e4Smiod 		  if (! ISPRINT (ri->u.buffer.data[i + j])
23913d8817e4Smiod 		      && ri->u.buffer.data[i + j] != 0)
23923d8817e4Smiod 		    break;
23933d8817e4Smiod 		if (j >= 2)
23943d8817e4Smiod 		  {
23953d8817e4Smiod 		    fprintf (e, "\t// ");
23963d8817e4Smiod 		    for (j = 0; j < 2; ++j)
23973d8817e4Smiod 		      {
23983d8817e4Smiod 			if (! ISPRINT (ri->u.buffer.data[i + j]))
23993d8817e4Smiod 			  fprintf (e, "\\%03o", ri->u.buffer.data[i + j]);
24003d8817e4Smiod 			else
24013d8817e4Smiod 			  {
24023d8817e4Smiod 			    if (ri->u.buffer.data[i + j] == '\\')
24033d8817e4Smiod 			      fprintf (e, "\\");
24043d8817e4Smiod 			    fprintf (e, "%c", ri->u.buffer.data[i + j]);
24053d8817e4Smiod 			  }
24063d8817e4Smiod 		      }
24073d8817e4Smiod 		  }
24083d8817e4Smiod 		fprintf (e, "\n");
24093d8817e4Smiod 		i += 2;
24103d8817e4Smiod 		first = 0;
24113d8817e4Smiod 	      }
24123d8817e4Smiod 
24133d8817e4Smiod 	    if (i < ri->u.buffer.length)
24143d8817e4Smiod 	      {
24153d8817e4Smiod 		if (! first)
24163d8817e4Smiod 		  indent (e, ind + 2);
24173d8817e4Smiod 		if ((ri->u.buffer.data[i] & 0x7f) == ri->u.buffer.data[i]
24183d8817e4Smiod 		    && ISPRINT (ri->u.buffer.data[i]))
24193d8817e4Smiod 		  fprintf (e, "\"%c\"", ri->u.buffer.data[i]);
24203d8817e4Smiod 		else
24213d8817e4Smiod 		  fprintf (e, "\"\\%03o\"", ri->u.buffer.data[i]);
24223d8817e4Smiod 		if (ri->next != NULL)
24233d8817e4Smiod 		  fprintf (e, ",");
24243d8817e4Smiod 		fprintf (e, "\n");
24253d8817e4Smiod 		first = 0;
24263d8817e4Smiod 	      }
24273d8817e4Smiod 
24283d8817e4Smiod 	    break;
24293d8817e4Smiod 	  }
24303d8817e4Smiod 	}
24313d8817e4Smiod 
24323d8817e4Smiod       if (ri->type != RCDATA_BUFFER)
24333d8817e4Smiod 	{
24343d8817e4Smiod 	  if (ri->next != NULL)
24353d8817e4Smiod 	    fprintf (e, ",");
24363d8817e4Smiod 	  fprintf (e, "\n");
24373d8817e4Smiod 	}
24383d8817e4Smiod     }
24393d8817e4Smiod 
24403d8817e4Smiod   indent (e, ind);
24413d8817e4Smiod   fprintf (e, "END\n");
24423d8817e4Smiod }
24433d8817e4Smiod 
24443d8817e4Smiod /* Write out a stringtable resource.  */
24453d8817e4Smiod 
24463d8817e4Smiod static void
write_rc_stringtable(FILE * e,const struct res_id * name,const struct stringtable * stringtable)24473d8817e4Smiod write_rc_stringtable (FILE *e, const struct res_id *name,
24483d8817e4Smiod 		      const struct stringtable *stringtable)
24493d8817e4Smiod {
24503d8817e4Smiod   unsigned long offset;
24513d8817e4Smiod   int i;
24523d8817e4Smiod 
24533d8817e4Smiod   if (name != NULL && ! name->named)
24543d8817e4Smiod     offset = (name->u.id - 1) << 4;
24553d8817e4Smiod   else
24563d8817e4Smiod     {
24573d8817e4Smiod       fprintf (e, "// %s string table name\n",
24583d8817e4Smiod 	       name == NULL ? "Missing" : "Invalid");
24593d8817e4Smiod       offset = 0;
24603d8817e4Smiod     }
24613d8817e4Smiod 
24623d8817e4Smiod   fprintf (e, "BEGIN\n");
24633d8817e4Smiod 
24643d8817e4Smiod   for (i = 0; i < 16; i++)
24653d8817e4Smiod     {
24663d8817e4Smiod       if (stringtable->strings[i].length != 0)
24673d8817e4Smiod 	{
24683d8817e4Smiod 	  fprintf (e, "  %lu, \"", offset + i);
24693d8817e4Smiod 	  unicode_print (e, stringtable->strings[i].string,
24703d8817e4Smiod 			 stringtable->strings[i].length);
24713d8817e4Smiod 	  fprintf (e, "\"\n");
24723d8817e4Smiod 	}
24733d8817e4Smiod     }
24743d8817e4Smiod 
24753d8817e4Smiod   fprintf (e, "END\n");
24763d8817e4Smiod }
24773d8817e4Smiod 
24783d8817e4Smiod /* Write out a versioninfo resource.  */
24793d8817e4Smiod 
24803d8817e4Smiod static void
write_rc_versioninfo(FILE * e,const struct versioninfo * versioninfo)24813d8817e4Smiod write_rc_versioninfo (FILE *e, const struct versioninfo *versioninfo)
24823d8817e4Smiod {
24833d8817e4Smiod   const struct fixed_versioninfo *f;
24843d8817e4Smiod   const struct ver_info *vi;
24853d8817e4Smiod 
24863d8817e4Smiod   f = versioninfo->fixed;
24873d8817e4Smiod   if (f->file_version_ms != 0 || f->file_version_ls != 0)
24883d8817e4Smiod     fprintf (e, " FILEVERSION %lu, %lu, %lu, %lu\n",
24893d8817e4Smiod 	     (f->file_version_ms >> 16) & 0xffff,
24903d8817e4Smiod 	     f->file_version_ms & 0xffff,
24913d8817e4Smiod 	     (f->file_version_ls >> 16) & 0xffff,
24923d8817e4Smiod 	     f->file_version_ls & 0xffff);
24933d8817e4Smiod   if (f->product_version_ms != 0 || f->product_version_ls != 0)
24943d8817e4Smiod     fprintf (e, " PRODUCTVERSION %lu, %lu, %lu, %lu\n",
24953d8817e4Smiod 	     (f->product_version_ms >> 16) & 0xffff,
24963d8817e4Smiod 	     f->product_version_ms & 0xffff,
24973d8817e4Smiod 	     (f->product_version_ls >> 16) & 0xffff,
24983d8817e4Smiod 	     f->product_version_ls & 0xffff);
24993d8817e4Smiod   if (f->file_flags_mask != 0)
25003d8817e4Smiod     fprintf (e, " FILEFLAGSMASK 0x%lx\n", f->file_flags_mask);
25013d8817e4Smiod   if (f->file_flags != 0)
25023d8817e4Smiod     fprintf (e, " FILEFLAGS 0x%lx\n", f->file_flags);
25033d8817e4Smiod   if (f->file_os != 0)
25043d8817e4Smiod     fprintf (e, " FILEOS 0x%lx\n", f->file_os);
25053d8817e4Smiod   if (f->file_type != 0)
25063d8817e4Smiod     fprintf (e, " FILETYPE 0x%lx\n", f->file_type);
25073d8817e4Smiod   if (f->file_subtype != 0)
25083d8817e4Smiod     fprintf (e, " FILESUBTYPE 0x%lx\n", f->file_subtype);
25093d8817e4Smiod   if (f->file_date_ms != 0 || f->file_date_ls != 0)
25103d8817e4Smiod     fprintf (e, "// Date: %lu, %lu\n", f->file_date_ms, f->file_date_ls);
25113d8817e4Smiod 
25123d8817e4Smiod   fprintf (e, "BEGIN\n");
25133d8817e4Smiod 
25143d8817e4Smiod   for (vi = versioninfo->var; vi != NULL; vi = vi->next)
25153d8817e4Smiod     {
25163d8817e4Smiod       switch (vi->type)
25173d8817e4Smiod 	{
25183d8817e4Smiod 	case VERINFO_STRING:
25193d8817e4Smiod 	  {
25203d8817e4Smiod 	    const struct ver_stringinfo *vs;
25213d8817e4Smiod 
25223d8817e4Smiod 	    fprintf (e, "  BLOCK \"StringFileInfo\"\n");
25233d8817e4Smiod 	    fprintf (e, "  BEGIN\n");
25243d8817e4Smiod 	    fprintf (e, "    BLOCK \"");
25253d8817e4Smiod 	    unicode_print (e, vi->u.string.language, -1);
25263d8817e4Smiod 	    fprintf (e, "\"\n");
25273d8817e4Smiod 	    fprintf (e, "    BEGIN\n");
25283d8817e4Smiod 
25293d8817e4Smiod 	    for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
25303d8817e4Smiod 	      {
25313d8817e4Smiod 		fprintf (e, "      VALUE \"");
25323d8817e4Smiod 		unicode_print (e, vs->key, -1);
25333d8817e4Smiod 		fprintf (e, "\", \"");
25343d8817e4Smiod 		unicode_print (e, vs->value, -1);
25353d8817e4Smiod 		fprintf (e, "\"\n");
25363d8817e4Smiod 	      }
25373d8817e4Smiod 
25383d8817e4Smiod 	    fprintf (e, "    END\n");
25393d8817e4Smiod 	    fprintf (e, "  END\n");
25403d8817e4Smiod 	    break;
25413d8817e4Smiod 	  }
25423d8817e4Smiod 
25433d8817e4Smiod 	case VERINFO_VAR:
25443d8817e4Smiod 	  {
25453d8817e4Smiod 	    const struct ver_varinfo *vv;
25463d8817e4Smiod 
25473d8817e4Smiod 	    fprintf (e, "  BLOCK \"VarFileInfo\"\n");
25483d8817e4Smiod 	    fprintf (e, "  BEGIN\n");
25493d8817e4Smiod 	    fprintf (e, "    VALUE \"");
25503d8817e4Smiod 	    unicode_print (e, vi->u.var.key, -1);
25513d8817e4Smiod 	    fprintf (e, "\"");
25523d8817e4Smiod 
25533d8817e4Smiod 	    for (vv = vi->u.var.var; vv != NULL; vv = vv->next)
25543d8817e4Smiod 	      fprintf (e, ", 0x%x, %d", (unsigned int) vv->language,
25553d8817e4Smiod 		       vv->charset);
25563d8817e4Smiod 
25573d8817e4Smiod 	    fprintf (e, "\n  END\n");
25583d8817e4Smiod 
25593d8817e4Smiod 	    break;
25603d8817e4Smiod 	  }
25613d8817e4Smiod 	}
25623d8817e4Smiod     }
25633d8817e4Smiod 
25643d8817e4Smiod   fprintf (e, "END\n");
25653d8817e4Smiod }
25663d8817e4Smiod 
25673d8817e4Smiod /* Write out data which would normally be read from a file.  */
25683d8817e4Smiod 
25693d8817e4Smiod static void
write_rc_filedata(FILE * e,unsigned long length,const unsigned char * data)25703d8817e4Smiod write_rc_filedata (FILE *e, unsigned long length, const unsigned char *data)
25713d8817e4Smiod {
25723d8817e4Smiod   unsigned long i;
25733d8817e4Smiod 
25743d8817e4Smiod   for (i = 0; i + 15 < length; i += 16)
25753d8817e4Smiod     {
25763d8817e4Smiod       fprintf (e, "// %4lx: ", i);
25773d8817e4Smiod       fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x ",
25783d8817e4Smiod 	       data[i + 0], data[i + 1], data[i + 2], data[i + 3],
25793d8817e4Smiod 	       data[i + 4], data[i + 5], data[i + 6], data[i + 7]);
25803d8817e4Smiod       fprintf (e, "%02x %02x %02x %02x %02x %02x %02x %02x\n",
25813d8817e4Smiod 	       data[i +  8], data[i +  9], data[i + 10], data[i + 11],
25823d8817e4Smiod 	       data[i + 12], data[i + 13], data[i + 14], data[i + 15]);
25833d8817e4Smiod     }
25843d8817e4Smiod 
25853d8817e4Smiod   if (i < length)
25863d8817e4Smiod     {
25873d8817e4Smiod       fprintf (e, "// %4lx:", i);
25883d8817e4Smiod       while (i < length)
25893d8817e4Smiod 	{
25903d8817e4Smiod 	  fprintf (e, " %02x", data[i]);
25913d8817e4Smiod 	  ++i;
25923d8817e4Smiod 	}
25933d8817e4Smiod       fprintf (e, "\n");
25943d8817e4Smiod     }
25953d8817e4Smiod }
2596