16 #include <my_global.h>
23 #define MAX_PRINT_INFO 32
38 longlong longlong_arg;
66 static const char *get_length(
const char *
fmt,
size_t *length, uint *pre_zero)
68 for (; my_isdigit(&my_charset_latin1, *fmt); fmt++)
70 *length= *length * 10 + (uint)(*fmt -
'0');
72 *pre_zero|= PREZERO_ARG;
88 static const char *get_width(
const char *fmt,
size_t *width)
90 for (; my_isdigit(&my_charset_latin1, *fmt); fmt++)
92 *width= *width * 10 + (uint)(*fmt -
'0');
107 static const char *check_longlong(
const char *fmt, uint *have_longlong)
114 *have_longlong= (
sizeof(long) ==
sizeof(longlong));
121 else if (*fmt ==
'z')
124 *have_longlong= (
sizeof(size_t) ==
sizeof(longlong));
144 static char *backtick_string(
const CHARSET_INFO *cs,
char *
to,
char *end,
145 char *par,
size_t par_len,
char quote_char)
149 char *par_end= par + par_len;
150 size_t buff_length= (size_t) (end - to);
152 if (buff_length <= par_len)
154 *start++= quote_char;
156 for ( ; par < par_end; par+= char_len)
158 uchar c= *(uchar *) par;
159 if (!(char_len= my_mbcharlen(cs, c)))
161 if (char_len == 1 && c == (uchar) quote_char )
163 if (start + 1 >= end)
165 *start++= quote_char;
167 if (start + char_len >= end)
169 start= strnmov(start, par, char_len);
172 if (start + 1 >= end)
174 *start++= quote_char;
187 static char *process_str_arg(
const CHARSET_INFO *cs,
char *to,
char *end,
188 size_t width,
char *par, uint print_type)
190 int well_formed_error;
191 size_t plen, left_len= (size_t) (end - to) + 1;
193 par = (
char*)
"(null)";
195 plen= strnlen(par, width);
196 if (left_len <= plen)
198 plen= cs->cset->well_formed_len(cs, par, par + plen,
199 width, &well_formed_error);
200 if (print_type & ESCAPED_ARG)
201 to= backtick_string(cs, to, end, par, plen,
'`');
203 to= strnmov(to,par,plen);
212 static char *process_bin_arg(
char *to,
char *end,
size_t width,
char *par)
214 DBUG_ASSERT(to <= end);
215 if (to + width + 1 > end)
217 memmove(to, par, width);
227 static char *process_dbl_arg(
char *to,
char *end,
size_t width,
228 double par,
char arg_type)
230 if (width == SIZE_T_MAX)
232 else if (width >= NOT_FIXED_DEC)
233 width= NOT_FIXED_DEC - 1;
234 width= MY_MIN(width, (
size_t)(end-to) - 1);
237 to+= my_fcvt(par, (
int)width , to, NULL);
239 to+= my_gcvt(par, MY_GCVT_ARG_DOUBLE, (
int) width , to, NULL);
248 static char *process_int_arg(
char *to,
char *end,
size_t length,
249 longlong par,
char arg_type, uint print_type)
251 size_t res_length, to_length;
252 char *store_start=
to, *store_end;
255 if ((to_length= (
size_t) (end-to)) < 16 || length)
258 if (arg_type ==
'd' || arg_type ==
'i')
259 store_end= longlong10_to_str(par, store_start, -10);
260 else if (arg_type ==
'u')
261 store_end= longlong10_to_str(par, store_start, 10);
262 else if (arg_type ==
'p')
266 store_end= ll2str(par, store_start + 2, 16, 0);
268 else if (arg_type ==
'o')
270 store_end= ll2str(par, store_start, 8, 0);
274 DBUG_ASSERT(arg_type ==
'X' || arg_type ==
'x');
275 store_end= ll2str(par, store_start, 16, (arg_type ==
'X'));
278 if ((res_length= (
size_t) (store_end - store_start)) > to_length)
281 if (store_start == buff)
283 length= MY_MIN(length, to_length);
284 if (res_length < length)
286 size_t diff= (length- res_length);
287 memset(to, (print_type & PREZERO_ARG) ?
'0' :
' ', diff);
288 if (arg_type ==
'p' && print_type & PREZERO_ARG)
298 bmove(to, store_start, res_length);
319 static char *process_args(
const CHARSET_INFO *cs,
char *to,
char *end,
320 const char* fmt,
size_t arg_index, va_list ap)
324 uint idx= 0, arg_count= arg_index;
329 print_arr[idx].flags= 0;
332 print_arr[idx].flags|= ESCAPED_ARG;
337 print_arr[idx].length= print_arr[idx].width= 0;
342 fmt= get_length(fmt, &print_arr[idx].length, &print_arr[idx].
flags);
343 print_arr[idx].length--;
344 DBUG_ASSERT(*fmt ==
'$' && print_arr[idx].length < MAX_ARGS);
345 args_arr[print_arr[idx].length].arg_type=
'd';
346 args_arr[print_arr[idx].length].have_longlong= 0;
347 print_arr[idx].flags|= LENGTH_ARG;
348 arg_count= MY_MAX(arg_count, print_arr[idx].length + 1);
352 fmt= get_length(fmt, &print_arr[idx].length, &print_arr[idx].
flags);
361 fmt= get_width(fmt, &print_arr[idx].width);
362 print_arr[idx].width--;
363 DBUG_ASSERT(*fmt ==
'$' && print_arr[idx].width < MAX_ARGS);
364 args_arr[print_arr[idx].width].arg_type=
'd';
365 args_arr[print_arr[idx].width].have_longlong= 0;
366 print_arr[idx].flags|= WIDTH_ARG;
367 arg_count= MY_MAX(arg_count, print_arr[idx].width + 1);
371 fmt= get_width(fmt, &print_arr[idx].width);
374 print_arr[idx].width= SIZE_T_MAX;
376 fmt= check_longlong(fmt, &args_arr[arg_index].have_longlong);
378 args_arr[arg_index].have_longlong= (
sizeof(
void *) ==
sizeof(longlong));
379 args_arr[arg_index].arg_type= print_arr[idx].arg_type= *
fmt;
381 print_arr[idx].arg_idx= arg_index;
382 print_arr[idx].begin= ++
fmt;
384 while (*fmt && *fmt !=
'%')
390 print_arr[idx].end=
fmt;
392 for (i= 0 ; i < arg_count; i++)
394 switch (args_arr[i].arg_type) {
397 args_arr[
i].str_arg= va_arg(ap,
char *);
401 args_arr[
i].double_arg= va_arg(ap,
double);
410 if (args_arr[i].have_longlong)
411 args_arr[
i].longlong_arg= va_arg(ap,longlong);
412 else if (args_arr[i].arg_type ==
'd' || args_arr[i].arg_type ==
'i')
413 args_arr[
i].longlong_arg= va_arg(ap,
int);
415 args_arr[
i].longlong_arg= va_arg(ap, uint);
418 args_arr[
i].longlong_arg= va_arg(ap,
int);
425 for (i= 0; i <= idx; i++)
427 size_t width= 0, length= 0;
428 switch (print_arr[i].arg_type) {
431 char *par= args_arr[print_arr[
i].arg_idx].str_arg;
432 width= (print_arr[
i].flags & WIDTH_ARG)
433 ? (
size_t)args_arr[print_arr[
i].width].longlong_arg
434 : print_arr[
i].width;
435 to= process_str_arg(cs, to, end, width, par, print_arr[i].
flags);
440 char *par = args_arr[print_arr[
i].arg_idx].str_arg;
441 width= (print_arr[
i].flags & WIDTH_ARG)
442 ? (
size_t)args_arr[print_arr[
i].width].longlong_arg
443 : print_arr[
i].width;
444 to= process_bin_arg(to, end, width, par);
451 *to++= (char) args_arr[print_arr[i].arg_idx].longlong_arg;
457 double d= args_arr[print_arr[
i].arg_idx].double_arg;
458 width= (print_arr[
i].flags & WIDTH_ARG) ?
459 (uint)args_arr[print_arr[
i].width].longlong_arg : print_arr[
i].width;
460 to= process_dbl_arg(to, end, width, d, print_arr[i].arg_type);
473 length= (print_arr[
i].flags & LENGTH_ARG)
474 ? (
size_t)args_arr[print_arr[
i].length].longlong_arg
475 : print_arr[
i].length;
477 if (args_arr[print_arr[i].arg_idx].have_longlong)
478 larg = args_arr[print_arr[
i].arg_idx].longlong_arg;
479 else if (print_arr[i].arg_type ==
'd' || print_arr[i].arg_type ==
'i' )
480 larg = (int) args_arr[print_arr[i].arg_idx].longlong_arg;
482 larg= (uint) args_arr[print_arr[i].arg_idx].longlong_arg;
484 to= process_int_arg(to, end, length, larg, print_arr[i].arg_type,
495 length= MY_MIN(end - to , print_arr[i].end - print_arr[i].begin);
496 if (to + length < end)
498 to= strnmov(to, print_arr[i].begin, length);
500 DBUG_ASSERT(to <= end);
507 DBUG_ASSERT(*fmt ==
'%');
508 print_arr[idx].end= fmt - 1;
512 fmt= get_width(fmt, &arg_index);
513 DBUG_ASSERT(*fmt ==
'$');
515 arg_count= MY_MAX(arg_count, arg_index);
539 size_t my_vsnprintf_ex(
const CHARSET_INFO *cs,
char *to,
size_t n,
540 const char* fmt, va_list ap)
542 char *start=
to, *end=to+n-1;
543 size_t length, width;
544 uint print_type, have_longlong;
561 if (my_isdigit(&my_charset_latin1, *fmt))
563 fmt= get_length(fmt, &length, &print_type);
566 to= process_args(cs, to, end, (fmt+1), length, ap);
567 return (
size_t) (to - start);
574 print_type|= ESCAPED_ARG;
582 length= va_arg(ap,
int);
585 fmt= get_length(fmt, &length, &print_type);
594 width= va_arg(ap,
int);
597 fmt= get_width(fmt, &width);
602 fmt= check_longlong(fmt, &have_longlong);
606 reg2
char *par= va_arg(ap,
char *);
607 to= process_str_arg(cs, to, end, width, par, print_type);
610 else if (*fmt ==
'b')
612 char *par = va_arg(ap,
char *);
613 to= process_bin_arg(to, end, width, par);
616 else if (*fmt ==
'f' || *fmt ==
'g')
618 double d= va_arg(ap,
double);
619 to= process_dbl_arg(to, end, width, d, *fmt);
622 else if (*fmt ==
'd' || *fmt ==
'i' || *fmt ==
'u' || *fmt ==
'x' ||
623 *fmt ==
'X' || *fmt ==
'p' || *fmt ==
'o')
628 have_longlong= (
sizeof(
void *) ==
sizeof(longlong));
631 larg = va_arg(ap,longlong);
632 else if (*fmt ==
'd' || *fmt ==
'i')
633 larg = va_arg(ap,
int);
635 larg= va_arg(ap, uint);
637 to= process_int_arg(to, end, length, larg, *fmt, print_type);
640 else if (*fmt ==
'c')
645 larg = va_arg(ap,
int);
655 DBUG_ASSERT(to <= end);
657 return (
size_t) (to - start);
668 size_t my_vsnprintf(
char *to,
size_t n,
const char* fmt, va_list ap)
670 return my_vsnprintf_ex(&my_charset_latin1, to, n, fmt, ap);
674 size_t my_snprintf(
char* to,
size_t n,
const char* fmt, ...)
679 result= my_vsnprintf(to, n, fmt, args);