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 30ef0b2..b54213b 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 e260792..e80cbc6 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 a0308df..62bc9fe 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 d620d8e..bafa956 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 b7bd656..bd6dd05 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 572145e..76404ca 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 8786415..8b3a389 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);