/* windres.c -- a program to manipulate Windows resources
- Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
- Free Software Foundation, Inc.
+ Copyright 1997-2013 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
Rewritten by Kai Tietz, Onevision.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
#include "sysdep.h"
#include <assert.h>
-#include <time.h>
#include "bfd.h"
#include "getopt.h"
#include "bucomm.h"
#include "obstack.h"
#include "windres.h"
-/* Defined in bfd/binary.c. Used to set architecture and machine of input
- binary files. */
-extern enum bfd_architecture bfd_external_binary_architecture;
-extern unsigned long bfd_external_machine;
-
/* Used by resrc.c at least. */
int verbose = 0;
int target_is_bigendian = 0;
const char *def_target_arch;
-static void set_endianess (bfd *, const char *);
+static void set_endianness (bfd *, const char *);
/* An enumeration of format types. */
void *
res_alloc (rc_uint_type bytes)
{
- return (void *) obstack_alloc (&res_obstack, (size_t) bytes);
+ return obstack_alloc (&res_obstack, (size_t) bytes);
}
/* We also use an obstack to save memory used while writing out a set
void *
reswr_alloc (rc_uint_type bytes)
{
- return (void *) obstack_alloc (&reswr_obstack, (size_t) bytes);
+ return obstack_alloc (&reswr_obstack, (size_t) bytes);
}
\f
/* Open a file using the include directory search list. */
if (*resources == NULL)
{
- static unsigned int timeval;
-
- /* Use the same timestamp for every resource created in a
- single run. */
- if (timeval == 0)
- timeval = time (NULL);
-
*resources = ((rc_res_directory *)
res_alloc (sizeof (rc_res_directory)));
(*resources)->characteristics = 0;
- (*resources)->time = timeval;
+ /* Using a real timestamp only serves to create non-deterministic
+ results. Use zero instead. */
+ (*resources)->time = 0;
(*resources)->major = 0;
(*resources)->minor = 0;
(*resources)->entries = NULL;
-O --output-format=<format> Specify output format\n\
-F --target=<target> Specify COFF target\n\
--preprocessor=<program> Program to use to preprocess rc file\n\
+ --preprocessor-arg=<arg> Additional preprocessor argument\n\
-I --include-dir=<dir> Include directory when preprocessing rc file\n\
-D --define <sym>[=<val>] Define SYM when preprocessing rc file\n\
-U --undefine <sym> Undefine SYM when preprocessing rc file\n\
-v --verbose Verbose - tells you what it's doing\n\
+ -c --codepage=<codepage> Specify default codepage\n\
-l --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\
/* Long options. */
-/* 150 isn't special; it's just an arbitrary non-ASCII char value. */
-
-#define OPTION_PREPROCESSOR 150
-#define OPTION_USE_TEMP_FILE (OPTION_PREPROCESSOR + 1)
-#define OPTION_NO_USE_TEMP_FILE (OPTION_USE_TEMP_FILE + 1)
-#define OPTION_YYDEBUG (OPTION_NO_USE_TEMP_FILE + 1)
+enum option_values
+{
+ /* 150 isn't special; it's just an arbitrary non-ASCII char value. */
+ OPTION_PREPROCESSOR = 150,
+ OPTION_USE_TEMP_FILE,
+ OPTION_NO_USE_TEMP_FILE,
+ OPTION_YYDEBUG,
+ OPTION_INCLUDE_DIR,
+ OPTION_PREPROCESSOR_ARG
+};
static const struct option long_options[] =
{
{"output-format", required_argument, 0, 'O'},
{"target", required_argument, 0, 'F'},
{"preprocessor", required_argument, 0, OPTION_PREPROCESSOR},
- {"include-dir", required_argument, 0, 'I'},
+ {"preprocessor-arg", required_argument, 0, OPTION_PREPROCESSOR_ARG},
+ {"include-dir", required_argument, 0, OPTION_INCLUDE_DIR},
{"define", required_argument, 0, 'D'},
{"undefine", required_argument, 0, 'U'},
{"verbose", no_argument, 0, 'v'},
+ {"codepage", required_argument, 0, 'c'},
{"language", required_argument, 0, 'l'},
{"use-temp-file", no_argument, 0, OPTION_USE_TEMP_FILE},
{"no-use-temp-file", no_argument, 0, OPTION_NO_USE_TEMP_FILE},
{0, no_argument, 0, 0}
};
+void
+windres_add_include_dir (const char *p)
+{
+ struct include_dir *n, **pp;
+
+ /* Computing paths is often complicated and error prone.
+ The easiest way to check for mistakes is at the time
+ we add them to include_dirs. */
+ assert (p != NULL);
+ assert (*p != '\0');
+
+ n = xmalloc (sizeof *n);
+ n->next = NULL;
+ n->dir = (char * ) p;
+
+ for (pp = &include_dirs; *pp != NULL; pp = &(*pp)->next)
+ ;
+ *pp = n;
+}
+
/* This keeps gcc happy when using -Wmissing-prototypes -Wstrict-prototypes. */
int main (int, char **);
language = 0x409; /* LANG_ENGLISH, SUBLANG_ENGLISH_US. */
use_temp_file = 0;
- while ((c = getopt_long (argc, argv, "f:i:l:o:I:J:O:F:D:U:rhHvV", long_options,
+ while ((c = getopt_long (argc, argv, "c:f:i:l:o:I:J:O:F:D:U:rhHvV", long_options,
(int *) 0)) != EOF)
{
switch (c)
{
+ case 'c':
+ {
+ rc_uint_type ncp;
+
+ if (optarg[0] == '0' && (optarg[1] == 'x' || optarg[1] == 'X'))
+ ncp = (rc_uint_type) strtol (optarg + 2, NULL, 16);
+ else
+ ncp = (rc_uint_type) strtol (optarg, NULL, 10);
+ if (ncp == CP_UTF16 || ! unicode_is_valid_codepage (ncp))
+ fatal (_("invalid codepage specified.\n"));
+ wind_default_codepage = wind_current_codepage = ncp;
+ }
+ break;
+
case 'i':
input_filename = optarg;
break;
preprocessor = optarg;
break;
+ case OPTION_PREPROCESSOR_ARG:
+ if (preprocargs == NULL)
+ {
+ quotedarg = quot (optarg);
+ preprocargs = xstrdup (quotedarg);
+ }
+ else
+ {
+ char *n;
+
+ quotedarg = quot (optarg);
+ n = xmalloc (strlen (preprocargs) + strlen (quotedarg) + 2);
+ sprintf (n, "%s %s", preprocargs, quotedarg);
+ free (preprocargs);
+ preprocargs = n;
+ }
+ break;
+
case 'D':
case 'U':
if (preprocargs == NULL)
input_format_tmp = format_from_name (optarg, 0);
if (input_format_tmp != RES_FORMAT_UNKNOWN)
{
- fprintf (stderr,
- _("Option -I is deprecated for setting the input format, please use -J instead.\n"));
- input_format = input_format_tmp;
- break;
+ struct stat statbuf;
+ char modebuf[11];
+
+ if (stat (optarg, & statbuf) == 0
+ /* Coded this way to avoid importing knowledge of S_ISDIR into this file. */
+ && (mode_string (statbuf.st_mode, modebuf), modebuf[0] == 'd'))
+ /* We have a -I option with a directory name that just happens
+ to match a format name as well. eg: -I res Assume that the
+ user knows what they are doing and do not complain. */
+ ;
+ else
+ {
+ fprintf (stderr,
+ _("Option -I is deprecated for setting the input format, please use -J instead.\n"));
+ input_format = input_format_tmp;
+ break;
+ }
}
+ /* Fall through. */
+ case OPTION_INCLUDE_DIR:
if (preprocargs == NULL)
{
quotedarg = quot (optarg);
preprocargs = n;
}
- {
- struct include_dir *n, **pp;
-
- n = (struct include_dir *) xmalloc (sizeof *n);
- n->next = NULL;
- n->dir = optarg;
-
- for (pp = &include_dirs; *pp != NULL; pp = &(*pp)->next)
- ;
- *pp = n;
- }
+ windres_add_include_dir (optarg);
break;
output_format = format_from_filename (output_filename, 0);
}
- set_endianess (NULL, target);
+ set_endianness (NULL, target);
/* Read the input file. */
switch (input_format)
return 0;
}
-static void set_endianess (bfd *abfd, const char *target)
+static void
+set_endianness (bfd *abfd, const char *target)
{
const bfd_target *target_vec;
def_target_arch = NULL;
- target_vec = bfd_find_target (target, abfd);
+ target_vec = bfd_get_target_info (target, abfd, &target_is_bigendian, NULL,
+ &def_target_arch);
if (! target_vec)
- fatal ("Can't detect target endianess and architecture.");
- target_is_bigendian = ((target_vec->byteorder == BFD_ENDIAN_BIG) ? 1 : 0);
- {
- const char *tname = target_vec->name;
- const char **arch = bfd_arch_list();
- if (arch && tname)
- {
- if (strchr (tname, '-') != NULL)
- tname = strchr (tname, '-') + 1;
- while (*arch != NULL)
- {
- const char *in_a = strstr (*arch, tname);
- char end_ch = (in_a ? in_a[strlen(tname)] : 0);
- if (in_a && (in_a == *arch || in_a[-1] == ':')
- && end_ch == 0)
- {
- def_target_arch = *arch;
- break;
- }
- arch++;
- }
- }
- if (! def_target_arch)
- fatal ("Can't detect architecture.");
- }
+ fatal ("Can't detect target endianness and architecture.");
+ if (! def_target_arch)
+ fatal ("Can't detect architecture.");
}
bfd *
}
void
-set_windres_bfd_endianess (windres_bfd *wrbfd, int is_bigendian)
+set_windres_bfd_endianness (windres_bfd *wrbfd, int is_bigendian)
{
assert (!! wrbfd);
switch (WR_KIND(wrbfd))
}
void
-set_windres_bfd_content(windres_bfd *wrbfd, const void *data, rc_uint_type off,
- rc_uint_type length)
+set_windres_bfd_content (windres_bfd *wrbfd, const void *data, rc_uint_type off,
+ rc_uint_type length)
{
if (WR_KIND(wrbfd) != WR_KIND_TARGET)
{
}
void
-get_windres_bfd_content(windres_bfd *wrbfd, void *data, rc_uint_type off,
- rc_uint_type length)
+get_windres_bfd_content (windres_bfd *wrbfd, void *data, rc_uint_type off,
+ rc_uint_type length)
{
if (WR_KIND(wrbfd) != WR_KIND_TARGET)
{