From 81472056d738c3b07914f3dad5edb0f4af45a050 Mon Sep 17 00:00:00 2001 From: Kai Tietz Date: Tue, 25 Oct 2011 08:03:18 +0000 Subject: [PATCH] 2011-10-25 Kai Tietz * 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 * binutils-all/windres/strtab4.rc: New test. * binutils-all/windres/strtab4.rsd: Likewise. --- binutils/ChangeLog | 10 +++ binutils/rcparse.y | 51 +++++++++-- binutils/resrc.c | 12 ++- binutils/testsuite/ChangeLog | 5 ++ .../testsuite/binutils-all/windres/strtab4.rc | 10 +++ .../binutils-all/windres/strtab4.rsd | 8 ++ binutils/windres.h | 2 +- binutils/winduni.c | 88 +++++++++++++++++++ binutils/winduni.h | 1 + 9 files changed, 175 insertions(+), 12 deletions(-) create mode 100644 binutils/testsuite/binutils-all/windres/strtab4.rc create mode 100644 binutils/testsuite/binutils-all/windres/strtab4.rsd diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 30ef0b26a04..b54213b55cf 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,13 @@ +2011-10-25 Kai Tietz + + * 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 * dwarf.c (read_and_display_attr_value) : Add CU_OFFSET diff --git a/binutils/rcparse.y b/binutils/rcparse.y index e2607929127..e80cbc60784 100644 --- a/binutils/rcparse.y +++ b/binutils/rcparse.y @@ -164,7 +164,7 @@ static const rc_res_id res_null_text = { 1, {{0, &null_unichar}}}; %type file_name %type res_unicode_string resname res_unicode_string_concat %type sizedstring -%type sizedunistring +%type sizedunistring res_unicode_sizedstring res_unicode_sizedstring_concat %type 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 { diff --git a/binutils/resrc.c b/binutils/resrc.c index a0308dfd902..62bc9fe588a 100644 --- a/binutils/resrc.c +++ b/binutils/resrc.c @@ -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 diff --git a/binutils/testsuite/ChangeLog b/binutils/testsuite/ChangeLog index d620d8e9878..bafa9561351 100644 --- a/binutils/testsuite/ChangeLog +++ b/binutils/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-10-25 Kai Tietz + + * binutils-all/windres/strtab4.rc: New test. + * binutils-all/windres/strtab4.rsd: Likewise. + 2011-10-11 Chris 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 index 00000000000..cd532980341 --- /dev/null +++ b/binutils/testsuite/binutils-all/windres/strtab4.rc @@ -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 index 00000000000..9fa055d7bd3 --- /dev/null +++ b/binutils/testsuite/binutils-all/windres/strtab4.rsd @@ -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 ........ diff --git a/binutils/windres.h b/binutils/windres.h index b7bd65621d7..bd6dd053e7b 100644 --- a/binutils/windres.h +++ b/binutils/windres.h @@ -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 *); diff --git a/binutils/winduni.c b/binutils/winduni.c index 572145effef..76404cace9f 100644 --- a/binutils/winduni.c +++ b/binutils/winduni.c @@ -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 '_'. */ diff --git a/binutils/winduni.h b/binutils/winduni.h index 878641535b4..8b3a389eb5f 100644 --- a/binutils/winduni.h +++ b/binutils/winduni.h @@ -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); -- 2.30.2