PR binutils/13297
[deliverable/binutils-gdb.git] / binutils / resrc.c
index 24b423d93e98f82056ba1912073c89d712dad74f..9d1abbc94e0095cbb8af4dd905db5b4c9ba00c34 100644 (file)
@@ -1,5 +1,5 @@
 /* resrc.c -- read and write Windows rc files.
-   Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007
+   Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007, 2008, 2011
    Free Software Foundation, Inc.
    Written by Ian Lance Taylor, Cygnus Support.
    Rewritten by Kai Tietz, Onevision.
@@ -8,7 +8,7 @@
 
    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 "windres.h"
 
 #include <assert.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>
@@ -281,7 +276,7 @@ run_cmd (char *cmd, const char *redir)
 
   if (pid == -1)
     {
-      fatal (_("%s %s: %s"), errmsg_fmt, errmsg_arg, strerror (errno));
+      fatal ("%s %s: %s", errmsg_fmt, errmsg_arg, strerror (errno));
       return 1;
     }
 
@@ -351,7 +346,33 @@ open_input_stream (char *cmd)
   return cpp_pipe;
 }
 
-/* look for the preprocessor program */
+/* Determine if FILENAME contains special characters that
+   can cause problems unless the entire filename is quoted.  */
+
+static int
+filename_need_quotes (const char *filename)
+{
+  if (filename == NULL || (filename[0] == '-' && filename[1] == 0))
+    return 0;
+
+  while (*filename != 0)
+    {
+      switch (*filename)
+        {
+        case '&':
+        case ' ':
+        case '<':
+        case '>':
+        case '|':
+        case '%':
+          return 1;
+        }
+      ++filename;
+    }
+  return 0;
+}
+
+/* Look for the preprocessor program.  */
 
 static FILE *
 look_for_default (char *cmd, const char *prefix, int end_prefix,
@@ -360,6 +381,7 @@ look_for_default (char *cmd, const char *prefix, int end_prefix,
   char *space;
   int found;
   struct stat s;
+  const char *fnquotes = (filename_need_quotes (filename) ? "\"" : "");
 
   strcpy (cmd, prefix);
 
@@ -390,8 +412,8 @@ look_for_default (char *cmd, const char *prefix, int end_prefix,
 
   strcpy (cmd, prefix);
 
-  sprintf (cmd + end_prefix, "%s %s %s",
-          DEFAULT_PREPROCESSOR, preprocargs, filename);
+  sprintf (cmd + end_prefix, "%s %s %s%s%s",
+          DEFAULT_PREPROCESSOR, preprocargs, fnquotes, filename, fnquotes);
 
   if (verbose)
     fprintf (stderr, _("Using `%s'\n"), cmd);
@@ -407,21 +429,60 @@ read_rc_file (const char *filename, const char *preprocessor,
              const char *preprocargs, int language, int use_temp_file)
 {
   char *cmd;
+  const char *fnquotes = (filename_need_quotes (filename) ? "\"" : "");
+
+  if (filename == NULL)
+    filename = "-";
+  /* Setup the default resource import path taken from input file.  */
+  else if (strchr (filename, '/') != NULL || strchr (filename, '\\') != NULL)
+    {
+      char *edit, *dir;
+
+      if (filename[0] == '/'
+         || filename[0] == '\\'
+         || filename[1] == ':')
+        /* Absolute path.  */
+       edit = dir = xstrdup (filename);
+      else
+       {
+         /* Relative path.  */
+         edit = dir = xmalloc (strlen (filename) + 3);
+         sprintf (dir, "./%s", filename);
+       }
+
+      /* Walk dir backwards stopping at the first directory separator.  */
+      edit += strlen (dir);
+      while (edit > dir && (edit[-1] != '\\' && edit[-1] != '/'))
+       {
+         --edit;
+         edit[0] = 0;
+       }
+
+      /* Cut off trailing slash.  */
+      --edit;
+      edit[0] = 0;
+
+      /* Convert all back slashes to forward slashes.  */
+      while ((edit = strchr (dir, '\\')) != NULL)
+       *edit = '/';
+
+      windres_add_include_dir (dir);
+    }
 
   istream_type = (use_temp_file) ? ISTREAM_FILE : ISTREAM_PIPE;
 
   if (preprocargs == NULL)
     preprocargs = "";
-  if (filename == NULL)
-    filename = "-";
 
   if (preprocessor)
     {
       cmd = xmalloc (strlen (preprocessor)
                     + strlen (preprocargs)
                     + strlen (filename)
+                    + strlen (fnquotes) * 2
                     + 10);
-      sprintf (cmd, "%s %s %s", preprocessor, preprocargs, filename);
+      sprintf (cmd, "%s %s %s%s%s", preprocessor, preprocargs,
+              fnquotes, filename, fnquotes);
 
       cpp_pipe = open_input_stream (cmd);
     }
@@ -435,6 +496,7 @@ read_rc_file (const char *filename, const char *preprocessor,
                     + strlen (preprocessor)
                     + strlen (preprocargs)
                     + strlen (filename)
+                    + strlen (fnquotes) * 2
 #ifdef HAVE_EXECUTABLE_SUFFIX
                     + strlen (EXECUTABLE_SUFFIX)
 #endif
@@ -528,7 +590,19 @@ close_input_stream (void)
   else
     {
       if (cpp_pipe != NULL)
-       pclose (cpp_pipe);
+        {
+         int err;
+         err = pclose (cpp_pipe);
+         /* We are reading from a pipe, therefore we don't
+             know if cpp failed or succeeded until pclose.  */
+         if (err != 0 || errno == ECHILD)
+           {
+             /* Since this is also run via xatexit, safeguard.  */
+             cpp_pipe = NULL;
+             cpp_temp_file = NULL;
+             fatal (_("preprocessing failed."));
+           }
+        }
     }
 
   /* Since this is also run via xatexit, safeguard.  */
@@ -549,7 +623,7 @@ yyerror (const char *msg)
 void
 rcparse_warning (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.  */
@@ -606,7 +680,8 @@ get_data (FILE *e, bfd_byte *p, rc_uint_type c, const char *msg)
   if (got == c)
     return;
 
-  fatal (_("%s: read of %lu returned %lu"), msg, (long) c, (long) got);
+  fatal (_("%s: read of %lu returned %lu"),
+        msg, (unsigned long) c, (unsigned long) got);
 }
 \f
 /* Define an accelerator resource.  */
@@ -1511,8 +1586,9 @@ define_rcdata_number (rc_uint_type val, int dword)
 
 void
 define_stringtable (const rc_res_res_info *resinfo,
-                   rc_uint_type stringid, const unichar *string)
+                   rc_uint_type stringid, const unichar *string, int len)
 {
+  unichar *h;
   rc_res_id id;
   rc_res_resource *r;
 
@@ -1536,9 +1612,12 @@ define_stringtable (const rc_res_res_info *resinfo,
 
       r->res_info = *resinfo;
     }
-
-  r->u.stringtable->strings[stringid & 0xf].length = unichar_len (string);
-  r->u.stringtable->strings[stringid & 0xf].string = unichar_dup (string);
+  h = (unichar *) res_alloc ((len + 1) * sizeof (unichar));
+  if (len)
+    memcpy (h, string, len * sizeof (unichar));
+  h[len] = 0;
+  r->u.stringtable->strings[stringid & 0xf].length = (rc_uint_type) len;
+  r->u.stringtable->strings[stringid & 0xf].string = h;
 }
 
 void
@@ -1723,16 +1802,15 @@ define_versioninfo (rc_res_id id, rc_uint_type language,
 /* Add string version info to a list of version information.  */
 
 rc_ver_info *
-append_ver_stringfileinfo (rc_ver_info *verinfo, const char *language,
-                          rc_ver_stringinfo *strings)
+append_ver_stringfileinfo (rc_ver_info *verinfo,
+                          rc_ver_stringtable *stringtables)
 {
   rc_ver_info *vi, **pp;
 
   vi = (rc_ver_info *) res_alloc (sizeof (rc_ver_info));
   vi->next = NULL;
   vi->type = VERINFO_STRING;
-  unicode_from_ascii ((rc_uint_type *) NULL, &vi->u.string.language, language);
-  vi->u.string.strings = strings;
+  vi->u.string.stringtables = stringtables;
 
   for (pp = &verinfo; *pp != NULL; pp = &(*pp)->next)
     ;
@@ -1741,6 +1819,25 @@ append_ver_stringfileinfo (rc_ver_info *verinfo, const char *language,
   return verinfo;
 }
 
+rc_ver_stringtable *
+append_ver_stringtable (rc_ver_stringtable *stringtable,
+                       const char *language,
+                       rc_ver_stringinfo *strings)
+{
+  rc_ver_stringtable *vst, **pp;
+
+  vst = (rc_ver_stringtable *) res_alloc (sizeof (rc_ver_stringtable));
+  vst->next = NULL;
+  unicode_from_ascii ((rc_uint_type *) NULL, &vst->language, language);
+  vst->strings = strings;
+
+  for (pp = &stringtable; *pp != NULL; pp = &(*pp)->next)
+    ;
+  *pp = vst;
+
+  return stringtable;
+}
+
 /* Add variable version info to a list of version information.  */
 
 rc_ver_info *
@@ -1846,7 +1943,7 @@ indent (FILE *e, int c)
    without the need to store it somewhere externally.  */
 
 void
-write_rc_file (const char *filename, const rc_res_directory *resources)
+write_rc_file (const char *filename, const rc_res_directory *res_dir)
 {
   FILE *e;
   rc_uint_type language;
@@ -1861,7 +1958,7 @@ write_rc_file (const char *filename, const rc_res_directory *resources)
     }
 
   language = (rc_uint_type) ((bfd_signed_vma) -1);
-  write_rc_directory (e, resources, (const rc_res_id *) NULL,
+  write_rc_directory (e, res_dir, (const rc_res_id *) NULL,
                      (const rc_res_id *) NULL, &language, 1);
 }
 
@@ -2553,7 +2650,13 @@ write_rc_dialog_control (FILE *e, const rc_dialog_control *control)
       ci = NULL;
     }
 
-  if (control->text.named || control->text.u.id != 0)
+  /* For EDITTEXT, COMBOBOX, LISTBOX, and SCROLLBAR don't dump text.  */
+  if ((control->text.named || control->text.u.id != 0)
+      && (!ci
+          || (ci->class != CTL_EDIT
+              && ci->class != CTL_COMBOBOX
+              && ci->class != CTL_LISTBOX
+              && ci->class != CTL_SCROLLBAR)))
     {
       fprintf (e, " ");
       res_id_print (e, control->text, 1);
@@ -2982,10 +3085,10 @@ write_rc_datablock (FILE *e, rc_uint_type length, const bfd_byte *data, int has_
                      {
              if (k == 0)
                plen  = fprintf (e, "0x%lxL",
-                                (long) windres_get_32 (&wrtarget, data + i, length - i));
+                                (unsigned long) windres_get_32 (&wrtarget, data + i, length - i));
                        else
                plen = fprintf (e, " 0x%lxL",
-                               (long) windres_get_32 (&wrtarget, data + i, length - i)) - 1;
+                               (unsigned long) windres_get_32 (&wrtarget, data + i, length - i)) - 1;
              if (has_next || (i + 4) < length)
                          {
                  if (plen>0 && plen < 11)
@@ -3131,7 +3234,7 @@ write_rc_stringtable (FILE *e, const rc_res_id *name,
     {
       if (stringtable->strings[i].length != 0)
        {
-         fprintf (e, "  %lu, ", (long) offset + i);
+         fprintf (e, "  %lu, ", (unsigned long) offset + i);
          unicode_print_quoted (e, stringtable->strings[i].string,
                         stringtable->strings[i].length);
          fprintf (e, "\n");
@@ -3184,25 +3287,31 @@ write_rc_versioninfo (FILE *e, const rc_versioninfo *versioninfo)
        {
        case VERINFO_STRING:
          {
+           const rc_ver_stringtable *vst;
            const rc_ver_stringinfo *vs;
 
            fprintf (e, "  BLOCK \"StringFileInfo\"\n");
            fprintf (e, "  BEGIN\n");
-           fprintf (e, "    BLOCK ");
-           unicode_print_quoted (e, vi->u.string.language, -1);
-           fprintf (e, "\n");
-           fprintf (e, "    BEGIN\n");
 
-           for (vs = vi->u.string.strings; vs != NULL; vs = vs->next)
+           for (vst = vi->u.string.stringtables; vst != NULL; vst = vst->next)
              {
-               fprintf (e, "      VALUE ");
-               unicode_print_quoted (e, vs->key, -1);
-               fprintf (e, ", ");
-               unicode_print_quoted (e, vs->value, -1);
+               fprintf (e, "    BLOCK ");
+               unicode_print_quoted (e, vst->language, -1);
+
                fprintf (e, "\n");
-             }
+               fprintf (e, "    BEGIN\n");
 
-           fprintf (e, "    END\n");
+               for (vs = vst->strings; vs != NULL; vs = vs->next)
+                 {
+                   fprintf (e, "      VALUE ");
+                   unicode_print_quoted (e, vs->key, -1);
+                   fprintf (e, ", ");
+                   unicode_print_quoted (e, vs->value, -1);
+                   fprintf (e, "\n");
+                 }
+
+               fprintf (e, "    END\n");
+             }
            fprintf (e, "  END\n");
            break;
          }
This page took 0.02878 seconds and 4 git commands to generate.