/* resrc.c -- read and write Windows rc files.
- Copyright 1997 Free Software Foundation, Inc.
+ Copyright 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
This file is part of GNU Binutils.
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
-/* This file contains function that read and write Windows rc files.
+/* This file contains functions that read and write Windows rc files.
These are text files that represent resources. */
#include "bfd.h"
#include "bucomm.h"
#include "libiberty.h"
+#include "safe-ctype.h"
#include "windres.h"
#include <assert.h>
-#include <ctype.h>
+#include <errno.h>
#include <sys/stat.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#else /* ! HAVE_SYS_WAIT_H */
+#if ! defined (_WIN32) || defined (__CYGWIN__)
+#ifndef WIFEXITED
+#define WIFEXITED(w) (((w)&0377) == 0)
+#endif
+#ifndef WIFSIGNALED
+#define WIFSIGNALED(w) (((w)&0377) != 0177 && ((w)&~0377) == 0)
+#endif
+#ifndef WTERMSIG
+#define WTERMSIG(w) ((w) & 0177)
+#endif
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(w) (((w) >> 8) & 0377)
+#endif
+#else /* defined (_WIN32) && ! defined (__CYGWIN__) */
+#ifndef WIFEXITED
+#define WIFEXITED(w) (((w) & 0xff) == 0)
+#endif
+#ifndef WIFSIGNALED
+#define WIFSIGNALED(w) (((w) & 0xff) != 0 && ((w) & 0xff) != 0x7f)
+#endif
+#ifndef WTERMSIG
+#define WTERMSIG(w) ((w) & 0x7f)
+#endif
+#ifndef WEXITSTATUS
+#define WEXITSTATUS(w) (((w) & 0xff00) >> 8)
+#endif
+#endif /* defined (_WIN32) && ! defined (__CYGWIN__) */
+#endif /* ! HAVE_SYS_WAIT_H */
+
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+
+#if defined (_WIN32) && ! defined (__CYGWIN__)
+#define popen _popen
+#define pclose _pclose
+#endif
/* The default preprocessor. */
-#define DEFAULT_PREPROCESSOR "gcc -E -xc-header -DRC_INVOKED"
+#define DEFAULT_PREPROCESSOR "gcc -E -xc -DRC_INVOKED"
/* We read the directory entries in a cursor or icon file into
instances of this structure. */
static FILE *cpp_pipe;
+/* The temporary file used if we're not using popen, so we can delete it
+ if we exit. */
+
+static char *cpp_temp_file;
+
+/* Input stream is either a file or a pipe. */
+
+static enum {ISTREAM_PIPE, ISTREAM_FILE} istream_type;
+
/* As we read the rc file, we attach information to this structure. */
static struct res_directory *resources;
/* Local functions. */
-static void close_pipe PARAMS ((void));
+static int run_cmd PARAMS ((char *, const char *));
+static FILE *open_input_stream PARAMS ((char *));
+static FILE *look_for_default PARAMS ((char *, const char *, int,
+ const char *, const char *));
+static void close_input_stream PARAMS ((void));
static void unexpected_eof PARAMS ((const char *));
static int get_word PARAMS ((FILE *, const char *));
static unsigned long get_long PARAMS ((FILE *, const char *));
PARAMS ((FILE *, unsigned char *, unsigned long, const char *));
static void define_fontdirs PARAMS ((void));
\f
+/* Run `cmd' and redirect the output to `redir'. */
+
+static int
+run_cmd (cmd, redir)
+ char *cmd;
+ const char *redir;
+{
+ char *s;
+ int pid, wait_status, retcode;
+ int i;
+ const char **argv;
+ char *errmsg_fmt, *errmsg_arg;
+ char *temp_base = choose_temp_base ();
+ int in_quote;
+ char sep;
+ int redir_handle = -1;
+ int stdout_save = -1;
+
+ /* Count the args. */
+ i = 0;
+
+ for (s = cmd; *s; s++)
+ if (*s == ' ')
+ i++;
+
+ i++;
+ argv = alloca (sizeof (char *) * (i + 3));
+ i = 0;
+ s = cmd;
+
+ while (1)
+ {
+ while (*s == ' ' && *s != 0)
+ s++;
+
+ if (*s == 0)
+ break;
+
+ in_quote = (*s == '\'' || *s == '"');
+ sep = (in_quote) ? *s++ : ' ';
+ argv[i++] = s;
+
+ while (*s != sep && *s != 0)
+ s++;
+
+ if (*s == 0)
+ break;
+
+ *s++ = 0;
+
+ if (in_quote)
+ s++;
+ }
+ argv[i++] = NULL;
+
+ /* Setup the redirection. We can't use the usual fork/exec and redirect
+ since we may be running on non-POSIX Windows host. */
+
+ fflush (stdout);
+ fflush (stderr);
+
+ /* Open temporary output file. */
+ redir_handle = open (redir, O_WRONLY | O_TRUNC | O_CREAT, 0666);
+ if (redir_handle == -1)
+ fatal (_("can't open temporary file `%s': %s"), redir,
+ strerror (errno));
+
+ /* Duplicate the stdout file handle so it can be restored later. */
+ stdout_save = dup (STDOUT_FILENO);
+ if (stdout_save == -1)
+ fatal (_("can't redirect stdout: `%s': %s"), redir, strerror (errno));
+
+ /* Redirect stdout to our output file. */
+ dup2 (redir_handle, STDOUT_FILENO);
+
+ pid = pexecute (argv[0], (char * const *) argv, program_name, temp_base,
+ &errmsg_fmt, &errmsg_arg, PEXECUTE_ONE | PEXECUTE_SEARCH);
+
+ /* Restore stdout to its previous setting. */
+ dup2 (stdout_save, STDOUT_FILENO);
+
+ /* Close reponse file. */
+ close (redir_handle);
+
+ if (pid == -1)
+ {
+ fatal (_("%s %s: %s"), errmsg_fmt, errmsg_arg, strerror (errno));
+ return 1;
+ }
+
+ retcode = 0;
+ pid = pwait (pid, &wait_status, 0);
+
+ if (pid == -1)
+ {
+ fatal (_("wait: %s"), strerror (errno));
+ retcode = 1;
+ }
+ else if (WIFSIGNALED (wait_status))
+ {
+ fatal (_("subprocess got fatal signal %d"), WTERMSIG (wait_status));
+ retcode = 1;
+ }
+ else if (WIFEXITED (wait_status))
+ {
+ if (WEXITSTATUS (wait_status) != 0)
+ {
+ fatal (_("%s exited with status %d"), cmd,
+ WEXITSTATUS (wait_status));
+ retcode = 1;
+ }
+ }
+ else
+ retcode = 1;
+
+ return retcode;
+}
+
+static FILE *
+open_input_stream (cmd)
+ char *cmd;
+{
+ if (istream_type == ISTREAM_FILE)
+ {
+ char *fileprefix;
+
+ fileprefix = choose_temp_base ();
+ cpp_temp_file = (char *) xmalloc (strlen (fileprefix) + 5);
+ sprintf (cpp_temp_file, "%s.irc", fileprefix);
+ free (fileprefix);
+
+ if (run_cmd (cmd, cpp_temp_file))
+ fatal (_("can't execute `%s': %s"), cmd, strerror (errno));
+
+ cpp_pipe = fopen (cpp_temp_file, FOPEN_RT);;
+ if (cpp_pipe == NULL)
+ fatal (_("can't open temporary file `%s': %s"),
+ cpp_temp_file, strerror (errno));
+
+ if (verbose)
+ fprintf (stderr,
+ _("Using temporary file `%s' to read preprocessor output\n"),
+ cpp_temp_file);
+ }
+ else
+ {
+ cpp_pipe = popen (cmd, FOPEN_RT);
+ if (cpp_pipe == NULL)
+ fatal (_("can't popen `%s': %s"), cmd, strerror (errno));
+ if (verbose)
+ fprintf (stderr, _("Using popen to read preprocessor output\n"));
+ }
+
+ xatexit (close_input_stream);
+ return cpp_pipe;
+}
+
+/* look for the preprocessor program */
+
+static FILE *
+look_for_default (cmd, prefix, end_prefix, preprocargs, filename)
+ char *cmd;
+ const char *prefix;
+ int end_prefix;
+ const char *preprocargs;
+ const char *filename;
+{
+ char *space;
+ int found;
+ struct stat s;
+
+ strcpy (cmd, prefix);
+
+ sprintf (cmd + end_prefix, "%s", DEFAULT_PREPROCESSOR);
+ space = strchr (cmd + end_prefix, ' ');
+ if (space)
+ *space = 0;
+
+ if (
+#if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32)
+ strchr (cmd, '\\') ||
+#endif
+ strchr (cmd, '/'))
+ {
+ found = (stat (cmd, &s) == 0
+#ifdef HAVE_EXECUTABLE_SUFFIX
+ || stat (strcat (cmd, EXECUTABLE_SUFFIX), &s) == 0
+#endif
+ );
+
+ if (! found)
+ {
+ if (verbose)
+ fprintf (stderr, _("Tried `%s'\n"), cmd);
+ return NULL;
+ }
+ }
+
+ strcpy (cmd, prefix);
+
+ sprintf (cmd + end_prefix, "%s %s %s",
+ DEFAULT_PREPROCESSOR, preprocargs, filename);
+
+ if (verbose)
+ fprintf (stderr, _("Using `%s'\n"), cmd);
+
+ cpp_pipe = open_input_stream (cmd);
+ return cpp_pipe;
+}
+
/* Read an rc file. */
struct res_directory *
-read_rc_file (filename, preprocessor, preprocargs, language)
+read_rc_file (filename, preprocessor, preprocargs, language, use_temp_file)
const char *filename;
const char *preprocessor;
const char *preprocargs;
int language;
+ int use_temp_file;
{
char *cmd;
- if (preprocessor == NULL)
- preprocessor = DEFAULT_PREPROCESSOR;
+ istream_type = (use_temp_file) ? ISTREAM_FILE : ISTREAM_PIPE;
if (preprocargs == NULL)
preprocargs = "";
if (filename == NULL)
filename = "-";
- cmd = xmalloc (strlen (preprocessor)
- + strlen (preprocargs)
- + strlen (filename)
- + 10);
- sprintf (cmd, "%s %s %s", preprocessor, preprocargs, filename);
+ if (preprocessor)
+ {
+ cmd = xmalloc (strlen (preprocessor)
+ + strlen (preprocargs)
+ + strlen (filename)
+ + 10);
+ sprintf (cmd, "%s %s %s", preprocessor, preprocargs, filename);
+
+ cpp_pipe = open_input_stream (cmd);
+ }
+ else
+ {
+ char *dash, *slash, *cp;
+
+ preprocessor = DEFAULT_PREPROCESSOR;
+
+ cmd = xmalloc (strlen (program_name)
+ + strlen (preprocessor)
+ + strlen (preprocargs)
+ + strlen (filename)
+#ifdef HAVE_EXECUTABLE_SUFFIX
+ + strlen (EXECUTABLE_SUFFIX)
+#endif
+ + 10);
+
+
+ dash = slash = 0;
+ for (cp = program_name; *cp; cp++)
+ {
+ if (*cp == '-')
+ dash = cp;
+ if (
+#if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32)
+ *cp == ':' || *cp == '\\' ||
+#endif
+ *cp == '/')
+ {
+ slash = cp;
+ dash = 0;
+ }
+ }
+
+ cpp_pipe = 0;
+
+ if (dash)
+ {
+ /* First, try looking for a prefixed gcc in the windres
+ directory, with the same prefix as windres */
+
+ cpp_pipe = look_for_default (cmd, program_name, dash-program_name+1,
+ preprocargs, filename);
+ }
+
+ if (slash && !cpp_pipe)
+ {
+ /* Next, try looking for a gcc in the same directory as
+ that windres */
+
+ cpp_pipe = look_for_default (cmd, program_name, slash-program_name+1,
+ preprocargs, filename);
+ }
+
+ if (!cpp_pipe)
+ {
+ /* Sigh, try the default */
+
+ cpp_pipe = look_for_default (cmd, "", 0, preprocargs, filename);
+ }
- cpp_pipe = popen (cmd, FOPEN_RT);
- if (cpp_pipe == NULL)
- fatal ("can't popen `%s': %s", cmd, strerror (errno));
+ }
- xatexit (close_pipe);
+ free (cmd);
rc_filename = xstrdup (filename);
rc_lineno = 1;
rcparse_set_language (language);
yyin = cpp_pipe;
yyparse ();
+ rcparse_discard_strings ();
- if (pclose (cpp_pipe) != 0)
- fprintf (stderr, "%s: warning: preprocessor failed\n", program_name);
- cpp_pipe = NULL;
+ close_input_stream ();
if (fontdirs != NULL)
define_fontdirs ();
return resources;
}
-/* Close the pipe if it is open. This is called via xatexit. */
+/* Close the input stream if it is open. */
-void
-close_pipe ()
+static void
+close_input_stream ()
{
- if (cpp_pipe != NULL)
- pclose (cpp_pipe);
+ if (istream_type == ISTREAM_FILE)
+ {
+ if (cpp_pipe != NULL)
+ fclose (cpp_pipe);
+
+ if (cpp_temp_file != NULL)
+ {
+ int errno_save = errno;
+
+ unlink (cpp_temp_file);
+ errno = errno_save;
+ free (cpp_temp_file);
+ }
+ }
+ else
+ {
+ if (cpp_pipe != NULL)
+ pclose (cpp_pipe);
+ }
+
+ /* Since this is also run via xatexit, safeguard. */
+ cpp_pipe = NULL;
+ cpp_temp_file = NULL;
}
/* Report an error while reading an rc file. */
rcparse_warning (msg)
const char *msg;
{
- fprintf (stderr, "%s:%d: %s\n", rc_filename, rc_lineno, msg);
+ fprintf (stderr, _("%s:%d: %s\n"), rc_filename, rc_lineno, msg);
}
/* Die if we get an unexpected end of file. */
unexpected_eof (msg)
const char *msg;
{
- fatal ("%s: unexpected EOF", msg);
+ fatal (_("%s: unexpected EOF"), msg);
}
/* Read a 16 bit word from a file. The data is assumed to be little
if (got == c)
return;
- fatal ("%s: read of %lu returned %lu", msg, c, got);
+ fatal (_("%s: read of %lu returned %lu"), msg, c, got);
}
\f
/* Define an accelerator resource. */
{
struct res_resource *r;
- r = define_standard_resource (&resources, RT_ACCELERATORS, id,
+ r = define_standard_resource (&resources, RT_ACCELERATOR, id,
resinfo->language, 0);
r->type = RES_TYPE_ACCELERATOR;
r->u.acc = data;
e = open_file_search (filename, FOPEN_RB, "bitmap file", &real_filename);
if (stat (real_filename, &s) < 0)
- fatal ("stat failed on bitmap file `%s': %s", real_filename,
+ fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
strerror (errno));
- data = (unsigned char *) xmalloc (s.st_size - BITMAP_SKIP);
+ data = (unsigned char *) res_alloc (s.st_size - BITMAP_SKIP);
for (i = 0; i < BITMAP_SKIP; i++)
getc (e);
type = get_word (e, real_filename);
count = get_word (e, real_filename);
if (type != 2)
- fatal ("cursor file `%s' does not contain cursor data", real_filename);
+ fatal (_("cursor file `%s' does not contain cursor data"), real_filename);
/* Read in the icon directory entries. */
struct cursor *c;
if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
- fatal ("%s: fseek to %lu failed: %s", real_filename,
+ fatal (_("%s: fseek to %lu failed: %s"), real_filename,
icondirs[i].offset, strerror (errno));
- data = (unsigned char *) xmalloc (icondirs[i].bytes);
+ data = (unsigned char *) res_alloc (icondirs[i].bytes);
get_data (e, data, icondirs[i].bytes, real_filename);
- c = (struct cursor *) xmalloc (sizeof *c);
+ c = (struct cursor *) res_alloc (sizeof *c);
c->xhotspot = icondirs[i].u.cursor.xhotspot;
c->yhotspot = icondirs[i].u.cursor.yhotspot;
c->length = icondirs[i].bytes;
{
struct group_cursor *cg;
- /* These manipulations of icondirs into cg are copied from rcl. */
-
- cg = (struct group_cursor *) xmalloc (sizeof *cg);
+ cg = (struct group_cursor *) res_alloc (sizeof *cg);
cg->next = NULL;
cg->width = icondirs[i].width;
cg->height = 2 * icondirs[i].height;
+
+ /* FIXME: What should these be set to? */
cg->planes = 1;
- cg->bits = 4;
- cg->bytes = icondirs[i].bytes + 8;
+ cg->bits = 1;
+
+ cg->bytes = icondirs[i].bytes + 4;
cg->index = first_cursor + i + 1;
*pp = cg;
pp = &(*pp)->next;
}
+ free (icondirs);
+
r = define_standard_resource (&resources, RT_GROUP_CURSOR, id,
resinfo->language, 0);
r->type = RES_TYPE_GROUP_CURSOR;
struct dialog *copy;
struct res_resource *r;
- copy = (struct dialog *) xmalloc (sizeof *copy);
+ copy = (struct dialog *) res_alloc (sizeof *copy);
*copy = *dialog;
r = define_standard_resource (&resources, RT_DIALOG, id,
struct dialog_control *
define_control (text, id, x, y, width, height, class, style, exstyle)
- char *text;
+ const char *text;
unsigned long id;
unsigned long x;
unsigned long y;
{
struct dialog_control *n;
- n = (struct dialog_control *) xmalloc (sizeof *n);
+ n = (struct dialog_control *) res_alloc (sizeof *n);
n->next = NULL;
n->id = id;
n->style = style;
n->height = height;
n->class.named = 0;
n->class.u.id = class;
- if (text != NULL)
- res_string_to_id (&n->text, text);
- else
- {
- n->text.named = 0;
- n->text.u.id = 0;
- }
- free (text);
+ if (text == NULL)
+ text = "";
+ res_string_to_id (&n->text, text);
n->data = NULL;
n->help = 0;
return n;
}
+struct dialog_control *
+define_icon_control (iid, id, x, y, style, exstyle, help, data, ex)
+ 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;
+{
+ struct dialog_control *n;
+ if (style == 0)
+ style = SS_ICON | WS_CHILD | WS_VISIBLE;
+ n = define_control (0, id, x, y, 0, 0, CTL_STATIC, style, exstyle);
+ n->text = iid;
+ if (help && !ex)
+ rcparse_warning (_("help ID requires DIALOGEX"));
+ if (data && !ex)
+ rcparse_warning (_("control data requires DIALOGEX"));
+ n->help = help;
+ n->data = data;
+
+ return n;
+}
+
/* Define a font resource. */
void
struct stat s;
unsigned char *data;
struct res_resource *r;
- struct fontdir *fd;
long offset;
+ long fontdatalength;
+ unsigned char *fontdata;
+ struct fontdir *fd;
const char *device, *face;
struct fontdir **pp;
e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
if (stat (real_filename, &s) < 0)
- fatal ("stat failed on bitmap file `%s': %s", real_filename,
+ fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
strerror (errno));
- data = (unsigned char *) xmalloc (s.st_size);
+ data = (unsigned char *) res_alloc (s.st_size);
get_data (e, data, s.st_size, real_filename);
++fonts;
- fd = (struct fontdir *) xmalloc (sizeof *fd);
+ fontdatalength = 58 + strlen (device) + strlen (face);
+ fontdata = (unsigned char *) res_alloc (fontdatalength);
+ memcpy (fontdata, data, 56);
+ strcpy ((char *) fontdata + 56, device);
+ strcpy ((char *) fontdata + 57 + strlen (device), face);
+
+ fd = (struct fontdir *) res_alloc (sizeof *fd);
fd->next = NULL;
fd->index = fonts;
- fd->length = 58 + strlen (device) + strlen (face);
- fd->data = (unsigned char *) xmalloc (fd->length);
-
- memcpy (fd->data, data, 56);
- strcpy ((char *) fd->data + 56, device);
- strcpy ((char *) fd->data + 57 + strlen (device), face);
+ fd->length = fontdatalength;
+ fd->data = fontdata;
for (pp = &fontdirs; *pp != NULL; pp = &(*pp)->next)
;
type = get_word (e, real_filename);
count = get_word (e, real_filename);
if (type != 1)
- fatal ("icon file `%s' does not contain icon data", real_filename);
+ fatal (_("icon file `%s' does not contain icon data"), real_filename);
/* Read in the icon directory entries. */
struct res_id name;
if (fseek (e, icondirs[i].offset, SEEK_SET) != 0)
- fatal ("%s: fseek to %lu failed: %s", real_filename,
+ fatal (_("%s: fseek to %lu failed: %s"), real_filename,
icondirs[i].offset, strerror (errno));
- data = (unsigned char *) xmalloc (icondirs[i].bytes);
+ data = (unsigned char *) res_alloc (icondirs[i].bytes);
get_data (e, data, icondirs[i].bytes, real_filename);
{
struct group_icon *cg;
- /* FIXME: rcl sets planes and bits based on colors, rather than
- just copying the values from the file. */
+ /* For some reason, at least in some files the planes and bits
+ are zero. We instead set them from the color. This is
+ copied from rcl. */
- cg = (struct group_icon *) xmalloc (sizeof *cg);
+ cg = (struct group_icon *) res_alloc (sizeof *cg);
cg->next = NULL;
cg->width = icondirs[i].width;
cg->height = icondirs[i].height;
cg->colors = icondirs[i].colorcount;
- cg->planes = icondirs[i].u.icon.planes;
- cg->bits = icondirs[i].u.icon.bits;
+
+ cg->planes = 1;
+ cg->bits = 0;
+ while ((1 << cg->bits) < cg->colors)
+ ++cg->bits;
+
cg->bytes = icondirs[i].bytes;
cg->index = first_icon + i + 1;
pp = &(*pp)->next;
}
+ free (icondirs);
+
r = define_standard_resource (&resources, RT_GROUP_ICON, id,
resinfo->language, 0);
r->type = RES_TYPE_GROUP_ICON;
const struct res_res_info *resinfo;
struct menuitem *menuitems;
{
+ struct menu *m;
struct res_resource *r;
+ m = (struct menu *) res_alloc (sizeof *m);
+ m->items = menuitems;
+ m->help = 0;
+
r = define_standard_resource (&resources, RT_MENU, id, resinfo->language, 0);
r->type = RES_TYPE_MENU;
- r->u.menu = menuitems;
+ r->u.menu = m;
r->res_info = *resinfo;
}
struct menuitem *
define_menuitem (text, menuid, type, state, help, menuitems)
- char *text;
+ const char *text;
int menuid;
unsigned long type;
unsigned long state;
{
struct menuitem *mi;
- mi = (struct menuitem *) xmalloc (sizeof *mi);
+ mi = (struct menuitem *) res_alloc (sizeof *mi);
mi->next = NULL;
mi->type = type;
mi->state = state;
mi->id = menuid;
- mi->text = text;
+ if (text == NULL)
+ mi->text = NULL;
+ else
+ unicode_from_ascii ((int *) NULL, &mi->text, text);
mi->help = help;
mi->popup = menuitems;
return mi;
&real_filename);
if (stat (real_filename, &s) < 0)
- fatal ("stat failed on bitmap file `%s': %s", real_filename,
+ fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
strerror (errno));
- data = (unsigned char *) xmalloc (s.st_size);
+ data = (unsigned char *) res_alloc (s.st_size);
get_data (e, data, s.st_size, real_filename);
define_rcdata (id, resinfo, data)
struct res_id id;
const struct res_res_info *resinfo;
- struct rcdata_data *data;
+ struct rcdata_item *data;
{
struct res_resource *r;
r->res_info = *resinfo;
}
-/* Add an rcdata_item to an rcdata resource. */
+/* Create an rcdata item holding a string. */
-struct rcdata_data *
-append_rcdata_item (data, item)
- struct rcdata_data *data;
- struct rcdata_item *item;
-{
- if (data == NULL)
- {
- data = (struct rcdata_data *) xmalloc (sizeof *data);
- data->first = item;
- data->last = item;
- }
- else
- {
- data->last->next = item;
- data->last = item;
- }
-
- return data;
-}
-
-/* Add a string to an rcdata resource. */
-
-struct rcdata_data *
-append_rcdata_string (data, string)
- struct rcdata_data *data;
- char *string;
+struct rcdata_item *
+define_rcdata_string (string, len)
+ const char *string;
+ unsigned long len;
{
struct rcdata_item *ri;
+ char *s;
- ri = (struct rcdata_item *) xmalloc (sizeof *ri);
+ ri = (struct rcdata_item *) res_alloc (sizeof *ri);
ri->next = NULL;
ri->type = RCDATA_STRING;
- ri->u.string = string;
+ ri->u.string.length = len;
+ s = (char *) res_alloc (len);
+ memcpy (s, string, len);
+ ri->u.string.s = s;
- return append_rcdata_item (data, ri);
+ return ri;
}
-/* Add a number to an rcdata resource. */
+/* Create an rcdata item holding a number. */
-struct rcdata_data *
-append_rcdata_number (data, val, dword)
- struct rcdata_data *data;
+struct rcdata_item *
+define_rcdata_number (val, dword)
unsigned long val;
int dword;
{
struct rcdata_item *ri;
- ri = (struct rcdata_item *) xmalloc (sizeof *ri);
+ ri = (struct rcdata_item *) res_alloc (sizeof *ri);
ri->next = NULL;
ri->type = dword ? RCDATA_DWORD : RCDATA_WORD;
ri->u.word = val;
- return append_rcdata_item (data, ri);
+ return ri;
}
/* Define a stringtable resource. This is called for each string
define_stringtable (resinfo, stringid, string)
const struct res_res_info *resinfo;
unsigned long stringid;
- char *string;
+ const char *string;
{
struct res_id id;
struct res_resource *r;
id.named = 0;
- id.u.id = stringid >> 4;
+ id.u.id = (stringid >> 4) + 1;
r = define_standard_resource (&resources, RT_STRING, id,
resinfo->language, 1);
r->type = RES_TYPE_STRINGTABLE;
r->u.stringtable = ((struct stringtable *)
- xmalloc (sizeof (struct stringtable)));
+ res_alloc (sizeof (struct stringtable)));
for (i = 0; i < 16; i++)
{
r->u.stringtable->strings[i].length = 0;
unicode_from_ascii (&r->u.stringtable->strings[stringid & 0xf].length,
&r->u.stringtable->strings[stringid & 0xf].string,
string);
- free (string);
}
/* Define a user data resource where the data is in the rc file. */
struct res_id id;
struct res_id type;
const struct res_res_info *resinfo;
- struct rcdata_data *data;
+ struct rcdata_item *data;
{
struct res_id ids[3];
struct res_resource *r;
e = open_file_search (filename, FOPEN_RB, "font file", &real_filename);
if (stat (real_filename, &s) < 0)
- fatal ("stat failed on bitmap file `%s': %s", real_filename,
+ fatal (_("stat failed on bitmap file `%s': %s"), real_filename,
strerror (errno));
- data = (unsigned char *) xmalloc (s.st_size);
+ data = (unsigned char *) res_alloc (s.st_size);
get_data (e, data, s.st_size, real_filename);
r = define_resource (&resources, 3, ids, 0);
r->type = RES_TYPE_USERDATA;
- r->u.userdata = ((struct rcdata_data *)
- xmalloc (sizeof (struct rcdata_data)));
- r->u.userdata->first = ((struct rcdata_item *)
- xmalloc (sizeof (struct rcdata_item)));
- r->u.userdata->last = r->u.userdata->first;
- r->u.userdata->first->next = NULL;
- r->u.userdata->first->type = RCDATA_BUFFER;
- r->u.userdata->first->u.buffer.length = s.st_size;
- r->u.userdata->first->u.buffer.data = data;
+ r->u.userdata = ((struct rcdata_item *)
+ res_alloc (sizeof (struct rcdata_item)));
+ r->u.userdata->next = NULL;
+ r->u.userdata->type = RCDATA_BUFFER;
+ r->u.userdata->u.buffer.length = s.st_size;
+ r->u.userdata->u.buffer.data = data;
r->res_info = *resinfo;
}
r = define_standard_resource (&resources, RT_VERSION, id, language, 0);
r->type = RES_TYPE_VERSIONINFO;
r->u.versioninfo = ((struct versioninfo *)
- xmalloc (sizeof (struct versioninfo)));
+ res_alloc (sizeof (struct versioninfo)));
r->u.versioninfo->fixed = fixedverinfo;
r->u.versioninfo->var = verinfo;
r->res_info.language = language;
struct ver_info *
append_ver_stringfileinfo (verinfo, language, strings)
struct ver_info *verinfo;
- char *language;
+ const char *language;
struct ver_stringinfo *strings;
{
struct ver_info *vi, **pp;
- vi = (struct ver_info *) xmalloc (sizeof *vi);
+ vi = (struct ver_info *) res_alloc (sizeof *vi);
vi->next = NULL;
vi->type = VERINFO_STRING;
- unicode_from_ascii ((unsigned short *) NULL, &vi->u.string.language,
- language);
- free (language);
+ unicode_from_ascii ((int *) NULL, &vi->u.string.language, language);
vi->u.string.strings = strings;
for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
struct ver_info *
append_ver_varfileinfo (verinfo, key, var)
struct ver_info *verinfo;
- char *key;
+ const char *key;
struct ver_varinfo *var;
{
struct ver_info *vi, **pp;
- vi = (struct ver_info *) xmalloc (sizeof *vi);
+ vi = (struct ver_info *) res_alloc (sizeof *vi);
vi->next = NULL;
vi->type = VERINFO_VAR;
- unicode_from_ascii ((unsigned short *) NULL, &vi->u.var.key, key);
- free (key);
+ unicode_from_ascii ((int *) NULL, &vi->u.var.key, key);
vi->u.var.var = var;
for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
struct ver_stringinfo *
append_verval (strings, key, value)
struct ver_stringinfo *strings;
- char *key;
- char *value;
+ const char *key;
+ const char *value;
{
struct ver_stringinfo *vs, **pp;
- vs = (struct ver_stringinfo *) xmalloc (sizeof *vs);
+ vs = (struct ver_stringinfo *) res_alloc (sizeof *vs);
vs->next = NULL;
- unicode_from_ascii ((unsigned short *) NULL, &vs->key, key);
- free (key);
- unicode_from_ascii ((unsigned short *) NULL, &vs->value, value);
- free (value);
+ unicode_from_ascii ((int *) NULL, &vs->key, key);
+ unicode_from_ascii ((int *) NULL, &vs->value, value);
for (pp = &strings; *pp != NULL; pp = &(*pp)->next)
;
{
struct ver_varinfo *vv, **pp;
- vv = (struct ver_varinfo *) xmalloc (sizeof *vv);
+ vv = (struct ver_varinfo *) res_alloc (sizeof *vv);
vv->next = NULL;
vv->language = language;
vv->charset = charset;
PARAMS ((FILE *, const struct dialog_control *));
static void write_rc_fontdir PARAMS ((FILE *, const struct fontdir *));
static void write_rc_group_icon PARAMS ((FILE *, const struct group_icon *));
-static void write_rc_menu PARAMS ((FILE *, const struct menuitem *, int, int));
-static void write_rc_rcdata PARAMS ((FILE *, const struct rcdata_data *, int));
+static void write_rc_menu PARAMS ((FILE *, const struct menu *, int));
+static void write_rc_menuitems
+ PARAMS ((FILE *, const struct menuitem *, int, int));
+static void write_rc_rcdata PARAMS ((FILE *, const struct rcdata_item *, int));
static void write_rc_stringtable
PARAMS ((FILE *, const struct res_id *, const struct stringtable *));
static void write_rc_versioninfo PARAMS ((FILE *, const struct versioninfo *));
{
e = fopen (filename, FOPEN_WT);
if (e == NULL)
- fatal ("can't open `%s' for output: %s", filename, strerror (errno));
+ fatal (_("can't open `%s' for output: %s"), filename, strerror (errno));
}
language = -1;
case 2:
/* If we're at level 2, the key of this resource is the name
- we are going to use in the rc printout. */
+ we are going to use in the rc printout. */
name = &re->id;
break;
/* If we're at level 3, then this key represents a language.
Use it to update the current language. */
if (! re->id.named
- && re->id.u.id != *language
+ && re->id.u.id != (unsigned long) (unsigned int) *language
&& (re->id.u.id & 0xffff) == re->id.u.id)
{
fprintf (e, "LANGUAGE %lu, %lu\n",
- re->id.u.id & 0xff, (re->id.u.id >> 8) & 0xff);
+ re->id.u.id & ((1 << SUBLANG_SHIFT) - 1),
+ (re->id.u.id >> SUBLANG_SHIFT) & 0xff);
*language = re->id.u.id;
}
break;
case RT_STRING: s = "stringtable"; break;
case RT_FONTDIR: s = "fontdir"; break;
case RT_FONT: s = "font"; break;
- case RT_ACCELERATORS: s = "accelerators"; break;
+ case RT_ACCELERATOR: s = "accelerators"; break;
case RT_RCDATA: s = "rcdata"; break;
case RT_MESSAGETABLE: s = "messagetable"; break;
case RT_GROUP_CURSOR: s = "group cursor"; break;
fprintf (e, "// Level %d: ", level);
res_id_print (e, re->id, 1);
fprintf (e, "\n");
- }
+ }
write_rc_directory (e, re->u.dir, type, name, language, level + 1);
}
case RES_TYPE_ACCELERATOR:
s = "ACCELERATOR";
- rt = RT_ACCELERATORS;
+ rt = RT_ACCELERATOR;
break;
case RES_TYPE_BITMAP:
if (rt != 0
&& type != NULL
- && (type->named || type->u.id != rt))
+ && (type->named || type->u.id != (unsigned long) rt))
{
fprintf (e, "// Unexpected resource type mismatch: ");
res_id_print (e, *type, 1);
if (res->res_info.language != 0 && res->res_info.language != *language)
fprintf (e, "%sLANGUAGE %d, %d\n",
modifiers ? "// " : "",
- res->res_info.language & 0xff,
- (res->res_info.language >> 8) & 0xff);
+ res->res_info.language & ((1<<SUBLANG_SHIFT)-1),
+ (res->res_info.language >> SUBLANG_SHIFT) & 0xff);
if (res->res_info.characteristics != 0)
fprintf (e, "%sCHARACTERISTICS %lu\n",
modifiers ? "// " : "",
break;
case RES_TYPE_MENU:
- write_rc_menu (e, res->u.menu, menuex, 0);
+ write_rc_menu (e, res->u.menu, menuex);
break;
case RES_TYPE_RCDATA:
fprintf (e, " ");
if ((acc->key & 0x7f) == acc->key
- && isprint ((unsigned char) acc->key)
+ && ISPRINT (acc->key)
&& (acc->flags & ACC_VIRTKEY) == 0)
{
fprintf (e, "\"%c\"", acc->key);
{
const struct dialog_control *control;
- if (dialog->style != 0)
- fprintf (e, "STYLE 0x%lx\n", dialog->style);
+ fprintf (e, "STYLE 0x%lx\n", dialog->style);
+
if (dialog->exstyle != 0)
fprintf (e, "EXSTYLE 0x%lx\n", dialog->exstyle);
- if (dialog->class.named || dialog->class.u.id != 0)
+
+ if ((dialog->class.named && dialog->class.u.n.length > 0)
+ || dialog->class.u.id != 0)
{
fprintf (e, "CLASS ");
- res_id_print (e, dialog->class, 0);
+ res_id_print (e, dialog->class, 1);
fprintf (e, "\n");
}
+
if (dialog->caption != NULL)
- fprintf (e, "CAPTION \"%s\"\n", dialog->caption);
- if (dialog->menu.named || dialog->menu.u.id != 0)
+ {
+ fprintf (e, "CAPTION \"");
+ unicode_print (e, dialog->caption, -1);
+ fprintf (e, "\"\n");
+ }
+
+ if ((dialog->menu.named && dialog->menu.u.n.length > 0)
+ || dialog->menu.u.id != 0)
{
fprintf (e, "MENU ");
res_id_print (e, dialog->menu, 0);
fprintf (e, "\n");
}
+
if (dialog->font != NULL)
{
- fprintf (e, "FONT %d, \"%s\"", dialog->pointsize, dialog->font);
+ fprintf (e, "FONT %d, \"", dialog->pointsize);
+ unicode_print (e, dialog->font, -1);
+ fprintf (e, "\"");
if (dialog->ex != NULL
- && (dialog->ex->weight != 0 || dialog->ex->italic != 0))
- fprintf (e, ", %d, %d", dialog->ex->weight, dialog->ex->italic);
+ && (dialog->ex->weight != 0
+ || dialog->ex->italic != 0
+ || dialog->ex->charset != 1))
+ fprintf (e, ", %d, %d, %d",
+ dialog->ex->weight, dialog->ex->italic, dialog->ex->charset);
fprintf (e, "\n");
}
|| ci->style == (control->style & 0xff)))
break;
}
-
- if (ci->name != NULL)
+ if (ci == NULL)
+ fprintf (e, "CONTROL");
+ else if (ci->name != NULL)
fprintf (e, "%s", ci->name);
else
fprintf (e, "CONTROL");
-
+
if (control->text.named || control->text.u.id != 0)
{
fprintf (e, " ");
fprintf (e, " %d, ", control->id);
- if (ci->name == NULL)
+ if (ci == NULL)
{
+ if (control->class.named)
+ fprintf (e, "\"");
res_id_print (e, control->class, 0);
+ if (control->class.named)
+ fprintf (e, "\"");
fprintf (e, ", 0x%lx, ", control->style);
}
/* Write out a menu resource. */
static void
-write_rc_menu (e, menuitems, menuex, ind)
+write_rc_menu (e, menu, menuex)
+ FILE *e;
+ const struct menu *menu;
+ int menuex;
+{
+ if (menu->help != 0)
+ fprintf (e, "// Help ID: %lu\n", menu->help);
+ write_rc_menuitems (e, menu->items, menuex, 0);
+}
+
+/* Write out menuitems. */
+
+static void
+write_rc_menuitems (e, menuitems, menuex, ind)
FILE *e;
const struct menuitem *menuitems;
int menuex;
if (mi->text == NULL)
fprintf (e, " \"\"");
else
- fprintf (e, " \"%s\"", mi->text);
+ {
+ fprintf (e, " \"");
+ unicode_print (e, mi->text, -1);
+ fprintf (e, "\"");
+ }
if (! menuex)
{
fprintf (e, "\n");
if (mi->popup != NULL)
- write_rc_menu (e, mi->popup, menuex, ind + 2);
+ write_rc_menuitems (e, mi->popup, menuex, ind + 2);
}
indent (e, ind);
static void
write_rc_rcdata (e, rcdata, ind)
FILE *e;
- const struct rcdata_data *rcdata;
+ const struct rcdata_item *rcdata;
int ind;
{
const struct rcdata_item *ri;
indent (e, ind);
fprintf (e, "BEGIN\n");
- for (ri = rcdata->first; ri != NULL; ri = ri->next)
+ for (ri = rcdata; ri != NULL; ri = ri->next)
{
if (ri->type == RCDATA_BUFFER && ri->u.buffer.length == 0)
continue;
break;
case RCDATA_STRING:
- fprintf (e, "\"%s\"", ri->u.string);
- break;
+ {
+ const char *s;
+ unsigned long i;
+
+ fprintf (e, "\"");
+ s = ri->u.string.s;
+ for (i = 0; i < ri->u.string.length; i++)
+ {
+ if (ISPRINT (*s))
+ putc (*s, e);
+ else
+ fprintf (e, "\\%03o", *s);
+ }
+ fprintf (e, "\"");
+ break;
+ }
case RCDATA_WSTRING:
fprintf (e, "L\"");
- unicode_print (e, ri->u.wstring, -1);
+ unicode_print (e, ri->u.wstring.w, ri->u.wstring.length);
fprintf (e, "\"");
break;
for (i = 0; i + 3 < ri->u.buffer.length; i += 4)
{
unsigned long l;
+ int j;
+ if (! first)
+ indent (e, ind + 2);
l = ((((((ri->u.buffer.data[i + 3] << 8)
| ri->u.buffer.data[i + 2]) << 8)
| ri->u.buffer.data[i + 1]) << 8)
| ri->u.buffer.data[i]);
- if (first)
- first = 0;
- else
+ fprintf (e, "%luL", l);
+ if (i + 4 < ri->u.buffer.length || ri->next != NULL)
+ fprintf (e, ",");
+ for (j = 0; j < 4; ++j)
+ if (! ISPRINT (ri->u.buffer.data[i + j])
+ && ri->u.buffer.data[i + j] != 0)
+ break;
+ if (j >= 4)
{
- fprintf (e, ",\n");
- indent (e, ind);
+ fprintf (e, "\t// ");
+ for (j = 0; j < 4; ++j)
+ {
+ if (! ISPRINT (ri->u.buffer.data[i + j]))
+ fprintf (e, "\\%03o", ri->u.buffer.data[i + j]);
+ else
+ {
+ if (ri->u.buffer.data[i + j] == '\\')
+ fprintf (e, "\\");
+ fprintf (e, "%c", ri->u.buffer.data[i + j]);
+ }
+ }
}
- fprintf (e, "%luL", l);
+ fprintf (e, "\n");
+ first = 0;
}
if (i + 1 < ri->u.buffer.length)
{
- int i;
-
- i = (ri->u.buffer.data[i + 1] << 8) | ri->u.buffer.data[i];
- if (first)
- first = 0;
- else
+ int s;
+ int j;
+
+ if (! first)
+ indent (e, ind + 2);
+ s = (ri->u.buffer.data[i + 1] << 8) | ri->u.buffer.data[i];
+ fprintf (e, "%d", s);
+ if (i + 2 < ri->u.buffer.length || ri->next != NULL)
+ fprintf (e, ",");
+ for (j = 0; j < 2; ++j)
+ if (! ISPRINT (ri->u.buffer.data[i + j])
+ && ri->u.buffer.data[i + j] != 0)
+ break;
+ if (j >= 2)
{
- fprintf (e, ",\n");
- indent (e, ind);
+ fprintf (e, "\t// ");
+ for (j = 0; j < 2; ++j)
+ {
+ if (! ISPRINT (ri->u.buffer.data[i + j]))
+ fprintf (e, "\\%03o", ri->u.buffer.data[i + j]);
+ else
+ {
+ if (ri->u.buffer.data[i + j] == '\\')
+ fprintf (e, "\\");
+ fprintf (e, "%c", ri->u.buffer.data[i + j]);
+ }
+ }
}
- fprintf (e, "%d", i);
+ fprintf (e, "\n");
i += 2;
+ first = 0;
}
if (i < ri->u.buffer.length)
{
- if (first)
- first = 0;
- else
- {
- fprintf (e, ",\n");
- indent (e, ind);
- }
+ if (! first)
+ indent (e, ind + 2);
if ((ri->u.buffer.data[i] & 0x7f) == ri->u.buffer.data[i]
- && isprint (ri->u.buffer.data[i]))
+ && ISPRINT (ri->u.buffer.data[i]))
fprintf (e, "\"%c\"", ri->u.buffer.data[i]);
else
- fprintf (e, "\"\%03o\"", ri->u.buffer.data[i]);
+ fprintf (e, "\"\\%03o\"", ri->u.buffer.data[i]);
+ if (ri->next != NULL)
+ fprintf (e, ",");
+ fprintf (e, "\n");
+ first = 0;
}
break;
}
}
- if (ri->next != NULL)
- fprintf (e, ",");
- fprintf (e, "\n");
+ if (ri->type != RCDATA_BUFFER)
+ {
+ if (ri->next != NULL)
+ fprintf (e, ",");
+ fprintf (e, "\n");
+ }
}
indent (e, ind);
int i;
if (name != NULL && ! name->named)
- offset = name->u.id << 4;
+ offset = (name->u.id - 1) << 4;
else
{
fprintf (e, "// %s string table name\n",