2011-10-25 Kai Tietz <ktietz@redhat.com>
authorKai Tietz <kai.tietz@onevision.com>
Tue, 25 Oct 2011 08:03:18 +0000 (08:03 +0000)
committerKai Tietz <kai.tietz@onevision.com>
Tue, 25 Oct 2011 08:03:18 +0000 (08:03 +0000)
* winduni.h (unicode_from_ascii_len): New prototype.
* winduni.c (unicode_from_ascii_len): New function.
* windres.h (define_stringtable): Add additional length argument.
* windres.c (define_stringtable): Add length argument for string.
* rcparse.y (res_unicode_sizedstring): New rule.
(res_unicode_sizedstring_concat): Likewise.
(string_data): Adjust rule.

2011-10-25  Kai Tietz  <ktietz@redhat.com>

* binutils-all/windres/strtab4.rc: New test.
* binutils-all/windres/strtab4.rsd: Likewise.

binutils/ChangeLog
binutils/rcparse.y
binutils/resrc.c
binutils/testsuite/ChangeLog
binutils/testsuite/binutils-all/windres/strtab4.rc [new file with mode: 0644]
binutils/testsuite/binutils-all/windres/strtab4.rsd [new file with mode: 0644]
binutils/windres.h
binutils/winduni.c
binutils/winduni.h

index 30ef0b26a04cf99d2a9852fa86e0994b72189871..b54213b55cf1953f10081287a40ca919f9510790 100644 (file)
@@ -1,3 +1,13 @@
+2011-10-25  Kai Tietz  <ktietz@redhat.com>
+
+       * winduni.h (unicode_from_ascii_len): New prototype.
+       * winduni.c (unicode_from_ascii_len): New function.
+       * windres.h (define_stringtable): Add additional length argument.
+       * windres.c (define_stringtable): Add length argument for string.
+       * rcparse.y (res_unicode_sizedstring): New rule.
+       (res_unicode_sizedstring_concat): Likewise.
+       (string_data): Adjust rule.
+
 2011-10-24  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
        * dwarf.c (read_and_display_attr_value) <DW_AT_import>: Add CU_OFFSET
index e260792912739d01e7072654cf3c82d7c217bfd2..e80cbc607842046160e9bf705c35917b306ad245 100644 (file)
@@ -164,7 +164,7 @@ static const rc_res_id res_null_text = { 1, {{0, &null_unichar}}};
 %type <s> file_name
 %type <uni> res_unicode_string resname res_unicode_string_concat
 %type <ss> sizedstring
-%type <suni> sizedunistring
+%type <suni> sizedunistring res_unicode_sizedstring res_unicode_sizedstring_concat
 %type <i> sizednumexpr sizedposnumexpr
 
 %left '|'
@@ -1260,20 +1260,20 @@ rcdata_data:
 
 stringtable:
          STRINGTABLE suboptions BEG 
-           { sub_res_info = $2; }
-           string_data END
+           { sub_res_info = $2; rcparse_rcdata (); }
+           string_data END { rcparse_normal (); }
        ;
 
 string_data:
          /* empty */
-       | string_data numexpr res_unicode_string_concat
+       | string_data numexpr res_unicode_sizedstring_concat
          {
-           define_stringtable (&sub_res_info, $2, $3);
+           define_stringtable (&sub_res_info, $2, $3.s, $3.length);
            rcparse_discard_strings ();
          }
-       | string_data numexpr ',' res_unicode_string_concat
+       | string_data numexpr ',' res_unicode_sizedstring_concat
          {
-           define_stringtable (&sub_res_info, $2, $4);
+           define_stringtable (&sub_res_info, $2, $4.s, $4.length);
            rcparse_discard_strings ();
          }
        | string_data error
@@ -1718,6 +1718,43 @@ res_unicode_string:
          }
        ;
 
+res_unicode_sizedstring:
+         sizedunistring
+         {
+           $$ = $1;
+         }
+       | sizedstring
+         {
+           unichar *h = NULL;
+           rc_uint_type l = 0;
+           unicode_from_ascii_len (&l, &h, $1.s, $1.length);
+           $$.s = h;
+           $$.length = l;
+         }
+       ;
+
+/* Concat string */
+res_unicode_sizedstring_concat:
+         res_unicode_sizedstring
+         {
+           $$ = $1;
+         }
+       |
+         res_unicode_sizedstring_concat res_unicode_sizedstring
+         {
+           rc_uint_type l1 = $1.length;
+           rc_uint_type l2 = $2.length;
+           unichar *h = (unichar *) res_alloc ((l1 + l2 + 1) * sizeof (unichar));
+           if (l1 != 0)
+             memcpy (h, $1.s, l1 * sizeof (unichar));
+           if (l2 != 0)
+             memcpy (h + l1, $2.s, l2  * sizeof (unichar));
+           h[l1 + l2] = 0;
+           $$.length = l1 + l2;
+           $$.s = h;
+         }
+       ;
+
 sizedstring:
          SIZEDSTRING
          {
index a0308dfd902a974d2fbee7ae1b5ecf87989a857a..62bc9fe588a04078a3473d652c669599ab5bb626 100644 (file)
@@ -1591,8 +1591,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;
 
@@ -1616,9 +1617,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
index d620d8e98788da6c6816151254fcaf70aecc3585..bafa95613517c6f019d1bbccf0d1ce26d618c3f2 100644 (file)
@@ -1,3 +1,8 @@
+2011-10-25  Kai Tietz  <ktietz@redhat.com>
+
+       * binutils-all/windres/strtab4.rc: New test.
+       * binutils-all/windres/strtab4.rsd: Likewise.
+
 2011-10-11  Chris  <player1@onet.eu>
 
        PR binutils/13051
diff --git a/binutils/testsuite/binutils-all/windres/strtab4.rc b/binutils/testsuite/binutils-all/windres/strtab4.rc
new file mode 100644 (file)
index 0000000..cd53298
--- /dev/null
@@ -0,0 +1,10 @@
+// cpparg -DTEST=1
+
+#include "windows.h"
+
+LANGUAGE 0, 0
+
+STRINGTABLE MOVEABLE PURE DISCARDABLE
+BEGIN
+  1 "hello\0 world"
+END
diff --git a/binutils/testsuite/binutils-all/windres/strtab4.rsd b/binutils/testsuite/binutils-all/windres/strtab4.rsd
new file mode 100644 (file)
index 0000000..9fa055d
--- /dev/null
@@ -0,0 +1,8 @@
+ 0000 00000000 20000000 ffff0000 ffff0000  .... ...........
+ 0010 00000000 00000000 00000000 00000000  ................
+ 0020 38000000 20000000 ffff0600 ffff0100  8... ...........
+ 0030 00000000 30100000 00000000 00000000  ....0...........
+ 0040 00000c00 68006500 6c006c00 6f000000  ....h.e.l.l.o...
+ 0050 20007700 6f007200 6c006400 00000000   .w.o.r.l.d.....
+ 0060 00000000 00000000 00000000 00000000  ................
+ 0070 00000000 00000000                    ........        
index b7bd65621d7a7892f21feb35b486adbe079ac8b1..bd6dd053e7b8e3ba763852e8c270508a6c0e15a7 100644 (file)
@@ -104,7 +104,7 @@ extern void define_rcdata_file  (rc_res_id, const rc_res_res_info *, const char
 extern rc_rcdata_item *define_rcdata_string (const char *, rc_uint_type);
 extern rc_rcdata_item *define_rcdata_unistring (const unichar *, rc_uint_type);
 extern rc_rcdata_item *define_rcdata_number (rc_uint_type, int);
-extern void define_stringtable (const rc_res_res_info *, rc_uint_type, const unichar *);
+extern void define_stringtable (const rc_res_res_info *, rc_uint_type, const unichar *, int);
 extern void define_user_data (rc_res_id, rc_res_id, const rc_res_res_info *, rc_rcdata_item *);
 extern void define_toolbar (rc_res_id, rc_res_res_info *, rc_uint_type ,rc_uint_type ,rc_toolbar_item *);
 extern void define_user_file (rc_res_id, rc_res_id, const rc_res_res_info *, const char *);
index 572145effefb3ee03845b26d9e7cba8402b7c973..76404cace9f9826576b08620f91c16c5def4848d 100644 (file)
@@ -194,6 +194,94 @@ unicode_from_ascii (rc_uint_type *length, unichar **unicode, const char *ascii)
   unicode_from_codepage (length, unicode, ascii, wind_current_codepage);
 }
 
+/* Convert an ASCII string with length A_LENGTH to a unicode string.  We just
+   copy it, expanding chars to shorts, rather than doing something intelligent.
+   This routine converts also \0 within a string.  */
+
+void
+unicode_from_ascii_len (rc_uint_type *length, unichar **unicode, const char *ascii, rc_uint_type a_length)
+{
+  char *tmp, *p;
+  rc_uint_type tlen, elen, idx = 0;
+
+  *unicode = NULL;
+
+  if (!a_length)
+    {
+      if (length)
+        *length = 0;
+      return;
+    }
+
+  /* Make sure we have zero terminated string.  */
+  p = tmp = (char *) alloca (a_length + 1);
+  memcpy (tmp, ascii, a_length);
+  tmp[a_length] = 0;
+
+  while (a_length > 0)
+    {
+      unichar *utmp, *up;
+
+      tlen = strlen (p);
+
+      if (tlen > a_length)
+        tlen = a_length;
+      if (*p == 0)
+        {
+         /* Make room for one more character.  */
+         utmp = (unichar *) res_alloc (sizeof (unichar) * (idx + 1));
+         if (idx > 0)
+           {
+             memcpy (utmp, *unicode, idx * sizeof (unichar));
+           }
+         *unicode = utmp;
+         utmp[idx++] = 0;
+         --a_length;
+         p++;
+         continue;
+       }
+      utmp = NULL;
+      elen = 0;
+      elen = wind_MultiByteToWideChar (wind_current_codepage, p, NULL, 0);
+      if (elen)
+       {
+         utmp = ((unichar *) res_alloc (elen + sizeof (unichar) * 2));
+         wind_MultiByteToWideChar (wind_current_codepage, p, utmp, elen);
+         elen /= sizeof (unichar);
+         elen --;
+       }
+      else
+        {
+         /* Make room for one more character.  */
+         utmp = (unichar *) res_alloc (sizeof (unichar) * (idx + 1));
+         if (idx > 0)
+           {
+             memcpy (utmp, *unicode, idx * sizeof (unichar));
+           }
+         *unicode = utmp;
+         utmp[idx++] = ((unichar) *p) & 0xff;
+         --a_length;
+         p++;
+         continue;
+       }
+      p += tlen;
+      a_length -= tlen;
+
+      up = (unichar *) res_alloc (sizeof (unichar) * (idx + elen));
+      if (idx > 0)
+       memcpy (up, *unicode, idx * sizeof (unichar));
+
+      *unicode = up;
+      if (elen)
+       memcpy (&up[idx], utmp, sizeof (unichar) * elen);
+
+      idx += elen;
+    }
+
+  if (length)
+    *length = idx;
+}
+
 /* Convert an unicode string to an ASCII string.  We just copy it,
    shrink shorts to chars, rather than doing something intelligent.
    Shorts with not within the char range are replaced by '_'.  */
index 878641535b495e0bb2ee1627c78da96eae622458..8b3a389eb5fbbf43f41c4cc616b72ecc0e540915 100644 (file)
@@ -126,6 +126,7 @@ extern const local_iconv_map *wind_find_codepage_info (unsigned);
 
 /* Convert an Codepage string to a unicode string.  */
 extern void unicode_from_codepage (rc_uint_type *, unichar **, const char *, rc_uint_type);
+extern void unicode_from_ascii_len (rc_uint_type *, unichar **, const char *, rc_uint_type );
 
 /* Convert an unicode string to an codepage string.  */
 extern void codepage_from_unicode (rc_uint_type *, const unichar *, char **, rc_uint_type);