PR binutils/16024
[binutils-gdb.git] / binutils / resrc.c
index ebed255157d33d34346a161579c1b64f25e3371f..bfc3bd4a445d352846f2d7c285c13cd8a243748e 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;
     }
 
@@ -328,7 +323,7 @@ open_input_stream (char *cmd)
       if (run_cmd (cmd, cpp_temp_file))
        fatal (_("can't execute `%s': %s"), cmd, strerror (errno));
 
-      cpp_pipe = fopen (cpp_temp_file, FOPEN_RT);;
+      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));
@@ -436,12 +431,48 @@ read_rc_file (const char *filename, const char *preprocessor,
   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)
     {
@@ -559,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.  */
@@ -580,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.  */
@@ -637,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.  */
@@ -1542,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;
 
@@ -1567,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
@@ -1754,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)
     ;
@@ -1772,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 *
@@ -1877,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;
@@ -1892,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);
 }
 
@@ -2584,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);
@@ -3013,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)
@@ -3162,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");
@@ -3215,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;
          }