1
/* Copyright (C) 2000 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
#include <my_global.h>
22
Limited snprintf() implementations
27
n Store up to n-1 characters, followed by an end 0
32
Supports following formats:
36
%#.#b Local format; note first # is ignored and second is REQUIRED
37
%#.#s Note first # is ignored
40
length of result string
43
size_t my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap)
45
char *start=to, *end=to+n-1;
47
uint pre_zero, have_long;
53
if (to == end) /* End of buffer */
55
*to++= *fmt; /* Copy ordinary char */
59
/* Read max fill size (only used with %d and %u) */
63
pre_zero= have_long= 0;
67
length= va_arg(ap, int);
70
for (; my_isdigit(&my_charset_latin1, *fmt); fmt++)
72
length= length * 10 + (uint)(*fmt - '0');
74
pre_zero= 1; /* first digit was 0 */
82
width= va_arg(ap, int);
85
for (; my_isdigit(&my_charset_latin1, *fmt); fmt++)
86
width= width * 10 + (uint)(*fmt - '0');
95
if (*fmt == 's') /* String parameter */
97
register char *par = va_arg(ap, char *);
98
size_t plen,left_len = (size_t) (end - to) + 1;
99
if (!par) par = (char*)"(null)";
100
plen= (uint) strnlen(par, width);
101
if (left_len <= plen)
103
to=strnmov(to,par,plen);
106
else if (*fmt == 'b') /* Buffer parameter */
108
char *par = va_arg(ap, char *);
109
DBUG_ASSERT(to <= end);
110
if (to + abs(width) + 1 > end)
111
width= end - to - 1; /* sign doesn't matter */
112
memmove(to, par, abs(width));
116
else if (*fmt == 'd' || *fmt == 'u'|| *fmt== 'x') /* Integer parameter */
119
size_t res_length, to_length;
120
char *store_start= to, *store_end;
123
if ((to_length= (size_t) (end-to)) < 16 || length)
126
larg = va_arg(ap, long);
129
larg = va_arg(ap, int);
131
larg= (long) (uint) va_arg(ap, int);
133
store_end= int10_to_str(larg, store_start, -10);
136
store_end= int10_to_str(larg, store_start, 10);
138
store_end= int2str(larg, store_start, 16, 0);
139
if ((res_length= (size_t) (store_end - store_start)) > to_length)
140
break; /* num doesn't fit in output */
141
/* If %#d syntax was used, we have to pre-zero/pre-space the string */
142
if (store_start == buff)
144
length= min(length, to_length);
145
if (res_length < length)
147
size_t diff= (length- res_length);
148
bfill(to, diff, pre_zero ? '0' : ' ');
151
bmove(to, store_start, res_length);
156
else if (*fmt == 'c') /* Character parameter */
161
larg = va_arg(ap, int);
166
/* We come here on '%%', unknown code or too long parameter */
169
*to++='%'; /* % used as % or unknown code */
171
DBUG_ASSERT(to <= end);
172
*to='\0'; /* End of errmessage */
173
return (size_t) (to - start);
177
size_t my_snprintf(char* to, size_t n, const char* fmt, ...)
182
result= my_vsnprintf(to, n, fmt, args);
188
#define OVERRUN_SENTRY 250
189
static void my_printf(const char * fmt, ...)
195
buf[sizeof(buf)-1]=OVERRUN_SENTRY;
196
n = my_vsnprintf(buf, sizeof(buf)-1,fmt, ar);
198
printf("n=%d, strlen=%d\n", n, strlen(buf));
199
if ((uchar) buf[sizeof(buf)-1] != OVERRUN_SENTRY)
201
fprintf(stderr, "Buffer overrun\n");
211
my_printf("Hello\n");
212
my_printf("Hello int, %d\n", 1);
213
my_printf("Hello string '%s'\n", "I am a string");
214
my_printf("Hello hack hack hack hack hack hack hack %d\n", 1);
215
my_printf("Hello %d hack %d\n", 1, 4);
216
my_printf("Hello %d hack hack hack hack hack %d\n", 1, 4);
217
my_printf("Hello '%s' hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\n", "hack");
218
my_printf("Hello hhhhhhhhhhhhhh %d sssssssssssssss\n", 1);
219
my_printf("Hello %u\n", 1);
220
my_printf("Hex: %lx '%6lx'\n", 32, 65);
221
my_printf("conn %ld to: '%-.64s' user: '%-.32s' host:\
222
`%-.64s' (%-.64s)", 1, 0,0,0,0);