This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[bintutils windres]: Allow \0 in stringtable strings


Hi,

this patch adds feature to windres that a string in a stringtable can
contain \0 elements.
This feature was requested by ReactOS people, as such things are
necessary in real-world Windows applications.

ChangeLog

2011-10-18  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.
	* testsuite/binutils-all/windres/strtab4.rc: New test.
	* testsuite/binutils-all/windres/strtab4.rsd: Likewise.

Tested and build for x86_64-w64-mingw32, i686-w64-mingw32, and
i686-pc-cygwin.  Ok for apply?

Regards,
Kai

Index: rcparse.y
===================================================================
RCS file: /cvs/src/src/binutils/rcparse.y,v
retrieving revision 1.31
diff -u -r1.31 rcparse.y
--- rcparse.y	11 Oct 2011 15:56:28 -0000	1.31
+++ rcparse.y	18 Oct 2011 18:11:13 -0000
@@ -164,7 +164,7 @@
 %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 @@

 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_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: resrc.c
===================================================================
RCS file: /cvs/src/src/binutils/resrc.c,v
retrieving revision 1.38
diff -u -r1.38 resrc.c
--- resrc.c	11 Oct 2011 15:56:28 -0000	1.38
+++ resrc.c	18 Oct 2011 18:11:14 -0000
@@ -1591,8 +1591,9 @@

 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 @@

       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: windres.h
===================================================================
RCS file: /cvs/src/src/binutils/windres.h,v
retrieving revision 1.18
diff -u -r1.18 windres.h
--- windres.h	11 Oct 2011 15:56:28 -0000	1.18
+++ windres.h	18 Oct 2011 18:11:14 -0000
@@ -104,7 +104,7 @@
 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: winduni.c
===================================================================
RCS file: /cvs/src/src/binutils/winduni.c,v
retrieving revision 1.14
diff -u -r1.14 winduni.c
--- winduni.c	2 Sep 2009 07:22:32 -0000	1.14
+++ winduni.c	18 Oct 2011 18:11:14 -0000
@@ -194,6 +194,94 @@
   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: winduni.h
===================================================================
RCS file: /cvs/src/src/binutils/winduni.h,v
retrieving revision 1.8
diff -u -r1.8 winduni.h
--- winduni.h	2 Sep 2009 07:22:32 -0000	1.8
+++ winduni.h	18 Oct 2011 18:11:14 -0000
@@ -126,6 +126,7 @@

 /* 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);

Attachment: strtab4.rc
Description: Binary data

Attachment: strtab4.rsd
Description: Binary data


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]