aboutsummaryrefslogtreecommitdiff
path: root/binutils/winduni.c
diff options
context:
space:
mode:
Diffstat (limited to 'binutils/winduni.c')
-rw-r--r--binutils/winduni.c213
1 files changed, 205 insertions, 8 deletions
diff --git a/binutils/winduni.c b/binutils/winduni.c
index cd02666..9def8df 100644
--- a/binutils/winduni.c
+++ b/binutils/winduni.c
@@ -2,6 +2,7 @@
Copyright 1997, 1998, 2000, 2001, 2003, 2007
Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support.
+ Rewritten by Kai Tietz, Onevision.
This file is part of GNU Binutils.
@@ -30,6 +31,7 @@
#include "sysdep.h"
#include "bfd.h"
+#include "bucomm.h"
#include "winduni.h"
#include "safe-ctype.h"
@@ -37,13 +39,16 @@
#include <windows.h>
#endif
+/* Prototypes. */
+static int unichar_isascii (const unichar *, rc_uint_type);
+
/* Convert an ASCII string to a unicode string. We just copy it,
expanding chars to shorts, rather than doing something intelligent. */
void
-unicode_from_ascii (int *length, unichar **unicode, const char *ascii)
+unicode_from_ascii (rc_uint_type *length, unichar **unicode, const char *ascii)
{
- int len;
+ rc_uint_type len;
#ifndef _WIN32
const char *s;
unsigned short *w;
@@ -57,11 +62,57 @@ unicode_from_ascii (int *length, unichar **unicode, const char *ascii)
/* We use MultiByteToWideChar rather than strlen to get the unicode
string length to allow multibyte "ascii" chars. The value returned
by this function includes the trailing '\0'. */
- len = MultiByteToWideChar (CP_ACP, 0, ascii, -1, NULL, 0);
+ len = (rc_uint_type) MultiByteToWideChar (CP_ACP, 0, ascii, -1, NULL, 0);
if (len)
{
*unicode = ((unichar *) res_alloc (len * sizeof (unichar)));
- MultiByteToWideChar (CP_ACP, 0, ascii, -1, *unicode, len);
+ MultiByteToWideChar (CP_ACP, 0, ascii, -1, *unicode, (int) len);
+ }
+ /* Discount the trailing '/0'. If MultiByteToWideChar failed,
+ this will set *length to -1. */
+ len--;
+#endif
+
+ if (length != NULL)
+ *length = len;
+}
+
+/* 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 '_'. */
+
+void
+ascii_from_unicode (rc_uint_type *length, const unichar *unicode, char **ascii)
+{
+ rc_uint_type len;
+#ifndef _WIN32
+ char *s;
+ const unsigned short *w;
+
+ len = 0;
+ while (unicode[len] != 0)
+ ++len;
+ *ascii = ((char *) res_alloc (len + 1));
+ for (s = *ascii, w = unicode; *w != '\0'; w++, s++)
+ {
+ if(w[0]==(w[0]&0xff))
+ *s = (char) w[0];
+ else
+ *s = '_';
+ }
+ *s = 0;
+#else
+ WINBOOL used_def = FALSE;
+ /* We use MultiByteToWideChar rather than strlen to get the unicode
+ string length to allow multibyte "ascii" chars. The value returned
+ by this function includes the trailing '\0'. */
+ len = (rc_uint_type) WideCharToMultiByte (CP_ACP, WC_DEFAULTCHAR, unicode, -1, NULL,
+ 0, "_", &used_def);
+ if (len)
+ {
+ *ascii = (char *) res_alloc (len * sizeof (char));
+ WideCharToMultiByte (CP_ACP, WC_DEFAULTCHAR, unicode, -1, *ascii, (int) len,
+ "_", &used_def);
}
/* Discount the trailing '/0'. If MultiByteToWideChar failed,
this will set *length to -1. */
@@ -78,7 +129,7 @@ unicode_from_ascii (int *length, unichar **unicode, const char *ascii)
some Windows function, probably WideCharToMultiByte. */
void
-unicode_print (FILE *e, const unichar *unicode, int length)
+unicode_print (FILE *e, const unichar *unicode, rc_uint_type length)
{
while (1)
{
@@ -86,12 +137,12 @@ unicode_print (FILE *e, const unichar *unicode, int length)
if (length == 0)
return;
- if (length > 0)
+ if ((bfd_signed_vma) length > 0)
--length;
ch = *unicode;
- if (ch == 0 && length < 0)
+ if (ch == 0 && (bfd_signed_vma) length < 0)
return;
++unicode;
@@ -99,7 +150,9 @@ unicode_print (FILE *e, const unichar *unicode, int length)
if ((ch & 0x7f) == ch)
{
if (ch == '\\')
- fputs ("\\", e);
+ fputs ("\\\\", e);
+ else if (ch == '"')
+ fputs ("\"\"", e);
else if (ISPRINT (ch))
putc (ch, e);
else
@@ -146,3 +199,147 @@ unicode_print (FILE *e, const unichar *unicode, int length)
fprintf (e, "\\x%x", (unsigned int) ch);
}
}
+
+/* Print a unicode string to a file. */
+void
+ascii_print (FILE *e, const char *s, rc_uint_type length)
+{
+ while (1)
+ {
+ char ch;
+
+ if (length == 0)
+ return;
+ if ((bfd_signed_vma) length > 0)
+ --length;
+
+ ch = *s;
+
+ if (ch == 0 && (bfd_signed_vma) length < 0)
+ return;
+
+ ++s;
+
+ if ((ch & 0x7f) == ch)
+ {
+ if (ch == '\\')
+ fputs ("\\\\", e);
+ else if (ch == '"')
+ fputs ("\"\"", e);
+ else if (ISPRINT (ch))
+ putc (ch, e);
+ else
+ {
+ switch (ch)
+ {
+ case ESCAPE_A:
+ fputs ("\\a", e);
+ break;
+
+ case ESCAPE_B:
+ fputs ("\\b", e);
+ break;
+
+ case ESCAPE_F:
+ fputs ("\\f", e);
+ break;
+
+ case ESCAPE_N:
+ fputs ("\\n", e);
+ break;
+
+ case ESCAPE_R:
+ fputs ("\\r", e);
+ break;
+
+ case ESCAPE_T:
+ fputs ("\\t", e);
+ break;
+
+ case ESCAPE_V:
+ fputs ("\\v", e);
+ break;
+
+ default:
+ fprintf (e, "\\%03o", (unsigned int) ch);
+ break;
+ }
+ }
+ }
+ else
+ fprintf (e, "\\%03o", (unsigned int) ch & 0xff);
+ }
+}
+
+rc_uint_type
+unichar_len (const unichar *unicode)
+{
+ rc_uint_type r = 0;
+ if (unicode)
+ while (unicode[r] != 0)
+ r++;
+ else
+ --r;
+ return r;
+}
+
+unichar *
+unichar_dup (const unichar *unicode)
+{
+ unichar *r;
+ int len;
+
+ if (! unicode)
+ return NULL;
+ for (len = 0; unicode[len] != 0; ++len)
+ ;
+ ++len;
+ r = ((unichar *) res_alloc (len * sizeof (unichar)));
+ memcpy (r, unicode, len * sizeof (unichar));
+ return r;
+}
+
+unichar *
+unichar_dup_uppercase (const unichar *u)
+{
+ unichar *r = unichar_dup (u);
+ int i;
+
+ if (! r)
+ return NULL;
+
+ for (i = 0; r[i] != 0; ++i)
+ {
+ if (r[i] >= 'a' && r[i] <= 'z')
+ r[i] &= 0xdf;
+ }
+ return r;
+}
+
+static int
+unichar_isascii (const unichar *u, rc_uint_type len)
+{
+ rc_uint_type i;
+ if ((bfd_signed_vma) len < 0)
+ {
+ if (u)
+ len = (rc_uint_type) unichar_len (u);
+ else
+ len = 0;
+ }
+
+ for (i = 0; i < len; i++)
+ if ((u[i] & 0xff80) != 0)
+ return 0;
+ return 1;
+}
+
+void
+unicode_print_quoted (FILE *e, const unichar *u, rc_uint_type len)
+{
+ if (! unichar_isascii (u, len))
+ fputc ('L', e);
+ fputc ('"', e);
+ unicode_print (e, u, len);
+ fputc ('"', e);
+}