aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--binutils/ChangeLog22
-rw-r--r--binutils/binutils.texi11
-rw-r--r--binutils/resrc.c275
-rw-r--r--binutils/windres.c23
-rw-r--r--binutils/windres.h2
5 files changed, 309 insertions, 24 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 98ce3bb..b20df8f 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,25 @@
+2000-01-07 Mumit Khan <khan@xraylith.wisc.edu>
+
+ * windres.c (long_options): Add --use-temp-file and
+ --no-use-temp-file options.
+ (usage): Document.
+ (main): Handle.
+
+ * windres.h: Update read_rc_file prototype.
+
+ * resrc.c (cpp_temp_file): New static variable.
+ (istream_type): New static variable.
+ (close_pipe): Delete function.
+ (run_cmd): New static function.
+ (open_input_stream): New static function.
+ (close_input_stream): New static function.
+ (look_for_default): Handle DOS directory separator. Use
+ open_input_stream instead of popen.
+ (read_rc_file): Likewise.
+
+ * binutils.texi: Document --use-temp-file, --no-use-temp-file
+ options.
+
2000-01-04 Mumit Khan <khan@xraylith.wisc.edu>
* dlltool.c (create_compat_implib): New variable.
diff --git a/binutils/binutils.texi b/binutils/binutils.texi
index 8ef446d..ff87412 100644
--- a/binutils/binutils.texi
+++ b/binutils/binutils.texi
@@ -2140,6 +2140,17 @@ Specify the default language to use when reading an @code{rc} file.
@var{val} should be a hexadecimal language code. The low eight bits are
the language, and the high eight bits are the sublanguage.
+@item --use-temp-file
+Use a temporary file to instead of using popen to read the output of
+the preprocessor. Use this option if the popen implementation is buggy
+on the host (eg., certain non-English language versions of Windows 95 and
+Windows 98 are known to have buggy popen where the output will instead
+go the console).
+
+@item --no-use-temp-file
+Use popen, not a temporary file, to read the output of the preprocessor.
+This is the default behaviour.
+
@item --help
Prints a usage summary.
diff --git a/binutils/resrc.c b/binutils/resrc.c
index 8ed6a5d..b38c75d 100644
--- a/binutils/resrc.c
+++ b/binutils/resrc.c
@@ -29,9 +29,50 @@
#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 */
#if defined (_WIN32) && ! defined (__CYGWIN32__)
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+
+#if defined (_WIN32) && ! defined (__CYGWIN__)
#define popen _popen
#define pclose _pclose
#endif
@@ -86,6 +127,15 @@ int rc_lineno;
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;
@@ -112,9 +162,11 @@ static int icons;
/* Local functions. */
+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_pipe PARAMS ((void));
+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 *));
@@ -122,6 +174,163 @@ static void get_data
PARAMS ((FILE *, unsigned char *, unsigned long, const char *));
static void define_fontdirs PARAMS ((void));
+/* 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 *
@@ -143,7 +352,11 @@ look_for_default (cmd, prefix, end_prefix, preprocargs, filename)
if (space)
*space = 0;
- if (strchr (cmd, '/'))
+ if (
+#if defined (__DJGPP__) || defined (__CYGWIN__) || defined (_WIN32)
+ strchr (cmd, '\\') ||
+#endif
+ strchr (cmd, '/'))
{
found = (stat (cmd, &s) == 0
#ifdef HAVE_EXECUTABLE_SUFFIX
@@ -154,7 +367,7 @@ look_for_default (cmd, prefix, end_prefix, preprocargs, filename)
if (! found)
{
if (verbose)
- fprintf (stderr, "Tried `%s'\n", cmd);
+ fprintf (stderr, _("Tried `%s'\n"), cmd);
return NULL;
}
}
@@ -165,23 +378,26 @@ look_for_default (cmd, prefix, end_prefix, preprocargs, filename)
DEFAULT_PREPROCESSOR, preprocargs, filename);
if (verbose)
- fprintf (stderr, "Using `%s'\n", cmd);
+ fprintf (stderr, _("Using `%s'\n"), cmd);
- cpp_pipe = popen (cmd, FOPEN_RT);
+ 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;
+ istream_type = (use_temp_file) ? ISTREAM_FILE : ISTREAM_PIPE;
+
if (preprocargs == NULL)
preprocargs = "";
if (filename == NULL)
@@ -195,7 +411,7 @@ read_rc_file (filename, preprocessor, preprocargs, language)
+ 10);
sprintf (cmd, "%s %s %s", preprocessor, preprocargs, filename);
- cpp_pipe = popen (cmd, FOPEN_RT);
+ cpp_pipe = open_input_stream (cmd);
}
else
{
@@ -219,7 +435,7 @@ read_rc_file (filename, preprocessor, preprocargs, language)
if (*cp == '-')
dash = cp;
if (
-#if defined(__DJGPP__) || defined (__CYGWIN__) || defined(__WIN32__)
+#if defined (__DJGPP__) || defined (__CYGWIN__) || defined(_WIN32)
*cp == ':' || *cp == '\\' ||
#endif
*cp == '/')
@@ -257,12 +473,9 @@ read_rc_file (filename, preprocessor, preprocargs, language)
}
}
- if (cpp_pipe == NULL)
- fatal (_("can't popen `%s': %s"), cmd, strerror (errno));
+
free (cmd);
- xatexit (close_pipe);
-
rc_filename = xstrdup (filename);
rc_lineno = 1;
if (language != -1)
@@ -270,10 +483,8 @@ read_rc_file (filename, preprocessor, preprocargs, language)
yyin = cpp_pipe;
yyparse ();
- 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 ();
@@ -283,13 +494,37 @@ read_rc_file (filename, preprocessor, preprocargs, language)
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. */
@@ -307,7 +542,7 @@ void
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. */
diff --git a/binutils/windres.c b/binutils/windres.c
index 0ccd909..3b24b47 100644
--- a/binutils/windres.c
+++ b/binutils/windres.c
@@ -113,7 +113,9 @@ static struct include_dir *include_dirs;
#define OPTION_INCLUDE_DIR (OPTION_HELP + 1)
#define OPTION_LANGUAGE (OPTION_INCLUDE_DIR + 1)
#define OPTION_PREPROCESSOR (OPTION_LANGUAGE + 1)
-#define OPTION_VERSION (OPTION_PREPROCESSOR + 1)
+#define OPTION_USE_TEMP_FILE (OPTION_PREPROCESSOR + 1)
+#define OPTION_NO_USE_TEMP_FILE (OPTION_USE_TEMP_FILE + 1)
+#define OPTION_VERSION (OPTION_NO_USE_TEMP_FILE + 1)
#define OPTION_YYDEBUG (OPTION_VERSION + 1)
static const struct option long_options[] =
@@ -126,6 +128,8 @@ static const struct option long_options[] =
{"output-format", required_argument, 0, 'O'},
{"preprocessor", required_argument, 0, OPTION_PREPROCESSOR},
{"target", required_argument, 0, 'F'},
+ {"use-temp-file", no_argument, 0, OPTION_USE_TEMP_FILE},
+ {"no-use-temp-file", no_argument, 0, OPTION_NO_USE_TEMP_FILE},
{"verbose", no_argument, 0, 'v'},
{"version", no_argument, 0, OPTION_VERSION},
{"yydebug", no_argument, 0, OPTION_YYDEBUG},
@@ -713,7 +717,10 @@ Options:\n\
-DSYM[=VAL], --define SYM[=VAL]\n\
Define SYM when preprocessing rc file\n\
-v Verbose - tells you what it's doing\n\
- --language VAL Set language when reading rc file\n"));
+ --language VAL Set language when reading rc file\n\
+ --use-temp-file Use a temporary file instead of popen to read\n\
+ the preprocessor output\n\
+ --no-use-temp-file Use popen (default)\n"));
#ifdef YYDEBUG
fprintf (stream, _("\
--yydebug Turn on parser debugging\n"));
@@ -777,6 +784,7 @@ main (argc, argv)
const char *quotedarg;
int language;
struct res_directory *resources;
+ int use_temp_file;
#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
setlocale (LC_MESSAGES, "");
@@ -800,6 +808,7 @@ main (argc, argv)
preprocessor = NULL;
preprocargs = NULL;
language = -1;
+ use_temp_file = 0;
while ((c = getopt_long (argc, argv, "i:o:I:O:F:D:v", long_options,
(int *) 0)) != EOF)
@@ -890,6 +899,14 @@ main (argc, argv)
language = strtol (optarg, (char **) NULL, 16);
break;
+ case OPTION_USE_TEMP_FILE:
+ use_temp_file = 1;
+ break;
+
+ case OPTION_NO_USE_TEMP_FILE:
+ use_temp_file = 0;
+ break;
+
#ifdef YYDEBUG
case OPTION_YYDEBUG:
yydebug = 1;
@@ -949,7 +966,7 @@ main (argc, argv)
abort ();
case RES_FORMAT_RC:
resources = read_rc_file (input_filename, preprocessor, preprocargs,
- language);
+ language, use_temp_file);
break;
case RES_FORMAT_RES:
resources = read_res_file (input_filename);
diff --git a/binutils/windres.h b/binutils/windres.h
index db43dd5..ba73612 100644
--- a/binutils/windres.h
+++ b/binutils/windres.h
@@ -747,7 +747,7 @@ extern int verbose;
/* Function declarations. */
extern struct res_directory *read_rc_file
- PARAMS ((const char *, const char *, const char *, int));
+ PARAMS ((const char *, const char *, const char *, int, int));
extern struct res_directory *read_res_file PARAMS ((const char *));
extern struct res_directory *read_coff_rsrc
PARAMS ((const char *, const char *));