summaryrefslogtreecommitdiff
path: root/strings
diff options
context:
space:
mode:
Diffstat (limited to 'strings')
-rw-r--r--strings/ctype-latin1.c11
-rw-r--r--strings/ctype-ucs2.c8
-rw-r--r--strings/ctype-utf8.c63
-rw-r--r--strings/decimal.c4
-rw-r--r--strings/my_strtoll10.c10
-rw-r--r--strings/my_vsnprintf.c190
6 files changed, 189 insertions, 97 deletions
diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c
index 80ae11c82c2..b642d6095c5 100644
--- a/strings/ctype-latin1.c
+++ b/strings/ctype-latin1.c
@@ -364,9 +364,14 @@ int my_mb_wc_latin1(CHARSET_INFO *cs __attribute__((unused)),
{
if (str >= end)
return MY_CS_TOOSMALL;
-
- *wc=cs_to_uni[*str];
- return (!wc[0] && str[0]) ? -1 : 1;
+ /*
+ There are no unassigned characters in latin1.
+ Every code point in latin1 is mapped to some Unicode code point.
+ We can always return 1, no needs to check the value of cs_to_uni[*str].
+ */
+ *wc= cs_to_uni[*str];
+ DBUG_ASSERT(wc[0] || !str[0]);
+ return 1;
}
static
diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c
index 6e18635f94b..fee272e5d35 100644
--- a/strings/ctype-ucs2.c
+++ b/strings/ctype-ucs2.c
@@ -40,11 +40,11 @@
#undef ULONGLONG_MAX
#define ULONGLONG_MAX (~(ulonglong) 0)
-#define MAX_NEGATIVE_NUMBER ((ulonglong) LL(0x8000000000000000))
+#define MAX_NEGATIVE_NUMBER ((ulonglong) 0x8000000000000000LL)
#define INIT_CNT 9
-#define LFACTOR ULL(1000000000)
-#define LFACTOR1 ULL(10000000000)
-#define LFACTOR2 ULL(100000000000)
+#define LFACTOR 1000000000ULL
+#define LFACTOR1 10000000000ULL
+#define LFACTOR2 100000000000ULL
#if defined(HAVE_CHARSET_utf32) || defined(HAVE_CHARSET_mb2)
static unsigned long lfactor[9]=
diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c
index edcac2774f8..03fba7e51e7 100644
--- a/strings/ctype-utf8.c
+++ b/strings/ctype-utf8.c
@@ -2459,46 +2459,33 @@ static int my_utf8_uni_no_range(CHARSET_INFO *cs __attribute__((unused)),
static int my_uni_utf8 (CHARSET_INFO *cs __attribute__((unused)),
my_wc_t wc, uchar *r, uchar *e)
{
- int count;
-
- if (r >= e)
- return MY_CS_TOOSMALL;
-
if (wc < 0x80)
- count = 1;
- else if (wc < 0x800)
- count = 2;
- else if (wc < 0x10000)
- count = 3;
-#ifdef UNICODE_32BIT
- else if (wc < 0x200000)
- count = 4;
- else if (wc < 0x4000000)
- count = 5;
- else if (wc <= 0x7fffffff)
- count = 6;
-#endif
- else return MY_CS_ILUNI;
-
- /*
- e is a character after the string r, not the last character of it.
- Because of it (r+count > e), not (r+count-1 >e )
- */
- if ( r+count > e )
- return MY_CS_TOOSMALLN(count);
-
- switch (count) {
- /* Fall through all cases!!! */
-#ifdef UNICODE_32BIT
- case 6: r[5] = (uchar) (0x80 | (wc & 0x3f)); wc = wc >> 6; wc |= 0x4000000;
- case 5: r[4] = (uchar) (0x80 | (wc & 0x3f)); wc = wc >> 6; wc |= 0x200000;
- case 4: r[3] = (uchar) (0x80 | (wc & 0x3f)); wc = wc >> 6; wc |= 0x10000;
-#endif
- case 3: r[2] = (uchar) (0x80 | (wc & 0x3f)); wc = wc >> 6; wc |= 0x800;
- case 2: r[1] = (uchar) (0x80 | (wc & 0x3f)); wc = wc >> 6; wc |= 0xc0;
- case 1: r[0] = (uchar) wc;
+ {
+ if (r >= e)
+ return MY_CS_TOOSMALL;
+ *r= (uchar) wc;
+ return 1;
}
- return count;
+ if (wc < 0x800)
+ {
+ if (r + 2 > e)
+ return MY_CS_TOOSMALLN(2);
+ /* U+0080..U+07FF: 00000xxx.xxyyyyyy -> 110xxxxx 10yyyyyy */
+ *r++= (uchar) (0xC0 | (wc >> 6));
+ *r= (uchar) (0x80 | (wc & 0x3F));
+ return 2;
+ }
+ if (wc < 0x10000)
+ {
+ if (r + 3 > e)
+ return MY_CS_TOOSMALLN(3);
+ /* U+0800..U+FFFF: xxxxyyyy.yyzzzzzz -> 1110xxxx 10yyyyyy 10zzzzzz */
+ *r++= (uchar) (0xE0 | (wc >> 12));
+ *r++= (uchar) (0x80 | ((wc >> 6) & 0x3f));
+ *r= (uchar) (0x80 | (wc & 0x3f));
+ return 3;
+ }
+ return MY_CS_ILUNI;
}
diff --git a/strings/decimal.c b/strings/decimal.c
index b36025ee8fc..30cc3c30428 100644
--- a/strings/decimal.c
+++ b/strings/decimal.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2004, 2013, Oracle and/or its affiliates.
- Copyright (c) 2009, 2011, Monty Program Ab.
+ Copyright (c) 2009, 2013, Monty Program Ab
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -1032,7 +1032,7 @@ int decimal2ulonglong(const decimal_t *from, ulonglong *to)
if (from->sign)
{
- *to=ULL(0);
+ *to= 0;
return E_DEC_OVERFLOW;
}
diff --git a/strings/my_strtoll10.c b/strings/my_strtoll10.c
index 89450f15c9f..ea556cea127 100644
--- a/strings/my_strtoll10.c
+++ b/strings/my_strtoll10.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2003 TXT DataKonsult Ab
- Copyright (c) 2009-2011, Monty Program Ab
+ Copyright (c) 2009, 2013, Monty Program Ab.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
@@ -29,11 +29,11 @@
#include "strings_def.h"
#include <my_sys.h> /* Needed for MY_ERRNO_ERANGE */
-#define MAX_NEGATIVE_NUMBER ((ulonglong) LL(0x8000000000000000))
+#define MAX_NEGATIVE_NUMBER ((ulonglong) 0x8000000000000000ULL)
#define INIT_CNT 9
-#define LFACTOR ULL(1000000000)
-#define LFACTOR1 ULL(10000000000)
-#define LFACTOR2 ULL(100000000000)
+#define LFACTOR 1000000000ULL
+#define LFACTOR1 10000000000ULL
+#define LFACTOR2 100000000000ULL
static unsigned long lfactor[9]=
{
diff --git a/strings/my_vsnprintf.c b/strings/my_vsnprintf.c
index 3ac4156da22..362dafb76ce 100644
--- a/strings/my_vsnprintf.c
+++ b/strings/my_vsnprintf.c
@@ -17,10 +17,14 @@
#include "strings_def.h"
#include <m_ctype.h>
#include <stdarg.h>
+#include <my_sys.h>
+#include <my_base.h>
+#include <my_handler_errors.h>
#define MAX_ARGS 32 /* max positional args count*/
#define MAX_PRINT_INFO 32 /* max print position count */
+#define MAX_WIDTH 65535
#define LENGTH_ARG 1
#define WIDTH_ARG 2
@@ -65,6 +69,7 @@ struct print_info
static const char *get_length(const char *fmt, size_t *length, uint *pre_zero)
{
+
for (; my_isdigit(&my_charset_latin1, *fmt); fmt++)
{
*length= *length * 10 + (uint)(*fmt - '0');
@@ -75,23 +80,28 @@ static const char *get_length(const char *fmt, size_t *length, uint *pre_zero)
}
-/**
- Calculates print width or index of positional argument
+/*
+ Get argument for '*' parameter
@param fmt processed string
- @param width print width or index of positional argument
+ @param args_arr Arguments to printf
+ @param arg_count Number of arguments to printf
+ @param length returns length of argument
+ @param flag returns flags with PREZERO_ARG set if necessary
- @retval
- string position right after width digits
+ @return new fmt
*/
-static const char *get_width(const char *fmt, size_t *width)
+static const char *get_length_arg(const char *fmt, ARGS_INFO *args_arr,
+ uint *arg_count, size_t *length, uint *flags)
{
- for (; my_isdigit(&my_charset_latin1, *fmt); fmt++)
- {
- *width= *width * 10 + (uint)(*fmt - '0');
- }
- return fmt;
+ fmt= get_length(fmt+1, length, flags);
+ *arg_count= max(*arg_count, (uint) *length);
+ (*length)--;
+ DBUG_ASSERT(*fmt == '$' && *length < MAX_ARGS);
+ args_arr[*length].arg_type= 'd';
+ args_arr[*length].have_longlong= 0;
+ return fmt+1;
}
/**
@@ -123,6 +133,8 @@ static const char *check_longlong(const char *fmt, uint *have_longlong)
fmt++;
*have_longlong= (sizeof(size_t) == sizeof(longlong));
}
+ else if (*fmt == 'p')
+ *have_longlong= (sizeof(void *) == sizeof(longlong));
return fmt;
}
@@ -227,7 +239,7 @@ static char *process_bin_arg(char *to, char *end, size_t width, char *par)
static char *process_dbl_arg(char *to, char *end, size_t width,
double par, char arg_type)
{
- if (width == SIZE_T_MAX)
+ if (width == MAX_WIDTH)
width= FLT_DIG; /* width not set, use default */
else if (width >= NOT_FIXED_DEC)
width= NOT_FIXED_DEC - 1; /* max.precision for my_fcvt() */
@@ -338,44 +350,31 @@ start:
/* Get print length */
if (*fmt == '*')
{
- fmt++;
- fmt= get_length(fmt, &print_arr[idx].length, &print_arr[idx].flags);
- print_arr[idx].length--;
- DBUG_ASSERT(*fmt == '$' && print_arr[idx].length < MAX_ARGS);
- args_arr[print_arr[idx].length].arg_type= 'd';
- args_arr[print_arr[idx].length].have_longlong= 0;
+ fmt= get_length_arg(fmt, args_arr, &arg_count, &print_arr[idx].length,
+ &print_arr[idx].flags);
print_arr[idx].flags|= LENGTH_ARG;
- arg_count= max(arg_count, print_arr[idx].length + 1);
- fmt++;
}
else
fmt= get_length(fmt, &print_arr[idx].length, &print_arr[idx].flags);
if (*fmt == '.')
{
+ uint unused_flags= 0;
fmt++;
/* Get print width */
if (*fmt == '*')
{
- fmt++;
- fmt= get_width(fmt, &print_arr[idx].width);
- print_arr[idx].width--;
- DBUG_ASSERT(*fmt == '$' && print_arr[idx].width < MAX_ARGS);
- args_arr[print_arr[idx].width].arg_type= 'd';
- args_arr[print_arr[idx].width].have_longlong= 0;
+ fmt= get_length_arg(fmt, args_arr, &arg_count, &print_arr[idx].width,
+ &unused_flags);
print_arr[idx].flags|= WIDTH_ARG;
- arg_count= max(arg_count, print_arr[idx].width + 1);
- fmt++;
}
else
- fmt= get_width(fmt, &print_arr[idx].width);
+ fmt= get_length(fmt, &print_arr[idx].width, &unused_flags);
}
else
- print_arr[idx].width= SIZE_T_MAX;
+ print_arr[idx].width= MAX_WIDTH;
fmt= check_longlong(fmt, &args_arr[arg_index].have_longlong);
- if (*fmt == 'p')
- args_arr[arg_index].have_longlong= (sizeof(void *) == sizeof(longlong));
args_arr[arg_index].arg_type= print_arr[idx].arg_type= *fmt;
print_arr[idx].arg_idx= arg_index;
@@ -414,6 +413,7 @@ start:
else
args_arr[i].longlong_arg= va_arg(ap, uint);
break;
+ case 'M':
case 'c':
args_arr[i].longlong_arg= va_arg(ap, int);
break;
@@ -474,17 +474,34 @@ start:
? (size_t)args_arr[print_arr[i].length].longlong_arg
: print_arr[i].length;
- if (args_arr[print_arr[i].arg_idx].have_longlong)
- larg = args_arr[print_arr[i].arg_idx].longlong_arg;
- else if (print_arr[i].arg_type == 'd' || print_arr[i].arg_type == 'i' )
- larg = (int) args_arr[print_arr[i].arg_idx].longlong_arg;
- else
- larg= (uint) args_arr[print_arr[i].arg_idx].longlong_arg;
-
+ larg = args_arr[print_arr[i].arg_idx].longlong_arg;
to= process_int_arg(to, end, length, larg, print_arr[i].arg_type,
print_arr[i].flags);
break;
}
+ case 'M':
+ {
+ longlong larg;
+ char *org_to= to;
+ char errmsg_buff[MYSYS_STRERROR_SIZE];
+
+ length= (print_arr[i].flags & WIDTH_ARG)
+ ? (size_t)args_arr[print_arr[i].width].longlong_arg
+ : print_arr[i].width;
+
+ larg = args_arr[print_arr[i].arg_idx].longlong_arg;
+ to= process_int_arg(to, end, 0, larg, 'd', print_arr[i].flags);
+ width-= (to - org_to);
+ if (width <= 4)
+ break;
+ *to++= ' ';
+ *to++= '"';
+ my_strerror(errmsg_buff, sizeof(errmsg_buff), (int) larg);
+ to= process_str_arg(cs, to, end, width-3, errmsg_buff,
+ print_arr[i].flags);
+ *to++= '"';
+ break;
+ }
default:
break;
}
@@ -492,6 +509,7 @@ start:
if (to == end)
break;
+ /* Copy data after the % format expression until next % */
length= min(end - to , print_arr[i].end - print_arr[i].begin);
if (to + length < end)
length++;
@@ -503,13 +521,14 @@ start:
}
else
{
+ uint unused_flags= 0;
/* Process next positional argument*/
DBUG_ASSERT(*fmt == '%');
print_arr[idx].end= fmt - 1;
idx++;
fmt++;
arg_index= 0;
- fmt= get_width(fmt, &arg_index);
+ fmt= get_length(fmt, &arg_index, &unused_flags);
DBUG_ASSERT(*fmt == '$');
fmt++;
arg_count= max(arg_count, arg_index);
@@ -587,6 +606,7 @@ size_t my_vsnprintf_ex(CHARSET_INFO *cs, char *to, size_t n,
if (*fmt == '.')
{
+ uint unused_flags= 0;
fmt++;
if (*fmt == '*')
{
@@ -594,10 +614,10 @@ size_t my_vsnprintf_ex(CHARSET_INFO *cs, char *to, size_t n,
width= va_arg(ap, int);
}
else
- fmt= get_width(fmt, &width);
+ fmt= get_length(fmt, &width, &unused_flags);
}
else
- width= SIZE_T_MAX;
+ width= MAX_WIDTH;
fmt= check_longlong(fmt, &have_longlong);
@@ -624,8 +644,6 @@ size_t my_vsnprintf_ex(CHARSET_INFO *cs, char *to, size_t n,
{
/* Integer parameter */
longlong larg;
- if (*fmt == 'p')
- have_longlong= (sizeof(void *) == sizeof(longlong));
if (have_longlong)
larg = va_arg(ap,longlong);
@@ -646,9 +664,27 @@ size_t my_vsnprintf_ex(CHARSET_INFO *cs, char *to, size_t n,
*to++= (char) larg;
continue;
}
+ else if (*fmt == 'M')
+ {
+ const char *org_to= to;
+ int larg= va_arg(ap, int);
+ to= process_int_arg(to, end, 0, larg, 'd', print_type);
+ width-= (to - org_to);
+ if ((end - to) >= 3 && (int) width >= 3)
+ {
+ char errmsg_buff[MYSYS_STRERROR_SIZE];
+ *to++= ' ';
+ *to++= '"';
+ my_strerror(errmsg_buff, sizeof(errmsg_buff), larg);
+ to= process_str_arg(cs, to, end, width-3, errmsg_buff, print_type);
+ if (end > to)
+ *to++= '"';
+ }
+ continue;
+ }
/* We come here on '%%', unknown code or too long parameter */
- if (to == end)
+ if (to >= end)
break;
*to++='%'; /* % used as % or unknown code */
}
@@ -744,3 +780,67 @@ int my_fprintf(FILE *stream, const char* format, ...)
va_end(args);
return result;
}
+
+
+/*
+ Return system error text for given error number
+
+ @param buf Buffer (of size MYSYS_STRERROR_SIZE)
+ @param len Length of buffer
+ @param nr Error number
+*/
+
+void my_strerror(char *buf, size_t len, int nr)
+{
+ char *msg= NULL;
+
+ buf[0]= '\0'; /* failsafe */
+
+ if (nr <= 0)
+ {
+ strmake(buf, (nr == 0 ?
+ "Internal error/check (Not system error)" :
+ "Internal error < 0 (Not system error)"),
+ len-1);
+ return;
+ }
+
+ /*
+ These (handler-) error messages are shared by perror, as required
+ by the principle of least surprise.
+ */
+ if ((nr >= HA_ERR_FIRST) && (nr <= HA_ERR_LAST))
+ {
+ msg= (char *) handler_error_messages[nr - HA_ERR_FIRST];
+ strmake(buf, msg, len - 1);
+ }
+ else
+ {
+ /*
+ On Windows, do things the Windows way. On a system that supports both
+ the GNU and the XSI variant, use whichever was configured (GNU); if
+ this choice is not advertised, use the default (POSIX/XSI). Testing
+ for __GNUC__ is not sufficient to determine whether this choice exists.
+ */
+#if defined(__WIN__)
+ strerror_s(buf, len, nr);
+#elif ((defined _POSIX_C_SOURCE && (_POSIX_C_SOURCE >= 200112L)) || \
+ (defined _XOPEN_SOURCE && (_XOPEN_SOURCE >= 600))) && \
+ ! defined _GNU_SOURCE
+ strerror_r(nr, buf, len); /* I can build with or without GNU */
+#elif defined _GNU_SOURCE
+ char *r= strerror_r(nr, buf, len);
+ if (r != buf) /* Want to help, GNU? */
+ strmake(buf, r, len - 1); /* Then don't. */
+#else
+ strerror_r(nr, buf, len);
+#endif
+ }
+
+ /*
+ strerror() return values are implementation-dependent, so let's
+ be pragmatic.
+ */
+ if (!buf[0])
+ strmake(buf, "unknown error", len - 1);
+}