diff options
Diffstat (limited to 'strings')
-rw-r--r-- | strings/ctype-latin1.c | 11 | ||||
-rw-r--r-- | strings/ctype-ucs2.c | 8 | ||||
-rw-r--r-- | strings/ctype-utf8.c | 63 | ||||
-rw-r--r-- | strings/decimal.c | 4 | ||||
-rw-r--r-- | strings/my_strtoll10.c | 10 | ||||
-rw-r--r-- | strings/my_vsnprintf.c | 190 |
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); +} |