This source file includes following definitions.
- parse_format_integer
- doprnt_non_null_end
- doprnt
- esprintf
- exprintf
- evxprintf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110 #include <config.h>
111 #include <stdio.h>
112 #include <stdlib.h>
113 #include <float.h>
114 #include <unistd.h>
115 #include <limits.h>
116
117 #include "lisp.h"
118
119
120
121
122 #include "character.h"
123
124
125 enum { SIZE_BOUND_EXTRA = DBL_MAX_10_EXP + 50 };
126
127
128
129
130 static char const *
131 parse_format_integer (char const *fmt, int *value)
132 {
133 int n = 0;
134 bool overflow = false;
135 for (; '0' <= *fmt && *fmt <= '9'; fmt++)
136 {
137 overflow |= ckd_mul (&n, n, 10);
138 overflow |= ckd_add (&n, n, *fmt - '0');
139 }
140 if (overflow || min (PTRDIFF_MAX, SIZE_MAX) - SIZE_BOUND_EXTRA < n)
141 error ("Format width or precision too large");
142 *value = n;
143 return fmt;
144 }
145
146
147
148
149
150
151 static ptrdiff_t
152 doprnt_non_null_end (char *buffer, ptrdiff_t bufsize, char const *format,
153 char const *format_end, va_list ap)
154 {
155 USE_SAFE_ALLOCA;
156 ptrdiff_t fmtlen = format_end - format;
157 char *fmt = SAFE_ALLOCA (fmtlen + 1);
158 memcpy (fmt, format, fmtlen);
159 fmt[fmtlen] = 0;
160 ptrdiff_t nbytes = doprnt (buffer, bufsize, fmt, NULL, ap);
161 SAFE_FREE ();
162 return nbytes;
163 }
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185 ptrdiff_t
186 doprnt (char *buffer, ptrdiff_t bufsize, const char *format,
187 const char *format_end, va_list ap)
188 {
189 if (format_end)
190 return doprnt_non_null_end (buffer, bufsize, format, format_end, ap);
191
192 const char *fmt = format;
193 char *bufptr = buffer;
194
195
196 char tembuf[SIZE_BOUND_EXTRA + 50];
197
198
199 ptrdiff_t size_allocated = sizeof (tembuf);
200
201
202 char *sprintf_buffer = tembuf;
203
204
205 char *big_buffer = NULL;
206
207 Lisp_Object quoting_style = Ftext_quoting_style ();
208
209 bufsize--;
210
211
212 while (*fmt && bufsize > 0)
213 {
214 char const *fmt0 = fmt;
215 char fmtchar = *fmt++;
216 if (fmtchar == '%')
217 {
218 ptrdiff_t width;
219 enum {
220 pDlen = sizeof pD - 1,
221 pIlen = sizeof pI - 1,
222 pMlen = sizeof PRIdMAX - 2,
223 maxmlen = max (max (1, pDlen), max (pIlen, pMlen))
224 };
225 enum {
226 no_modifier, long_modifier, pD_modifier, pI_modifier, pM_modifier
227 } length_modifier = no_modifier;
228 static char const modifier_len[] = { 0, 1, pDlen, pIlen, pMlen };
229 int mlen;
230 char charbuf[MAX_MULTIBYTE_LENGTH + 1];
231
232
233 int wid = 0, prec = -1;
234
235
236
237 char fmtstar[sizeof "%-+ 0*.*d" + maxmlen];
238 char *string = fmtstar;
239 *string++ = '%';
240
241
242 bool minusflag = false, plusflag = false, zeroflag = false,
243 spaceflag = false;
244 for (;; fmt++)
245 {
246 *string = *fmt;
247 switch (*fmt)
248 {
249 case '-': string += !minusflag; minusflag = true; continue;
250 case '+': string += !plusflag; plusflag = true; continue;
251 case ' ': string += !spaceflag; spaceflag = true; continue;
252 case '0': string += !zeroflag; zeroflag = true; continue;
253 }
254 break;
255 }
256
257
258 if ('1' <= *fmt && *fmt <= '9')
259 fmt = parse_format_integer (fmt, &wid);
260 if (*fmt == '.')
261 fmt = parse_format_integer (fmt + 1, &prec);
262 *string++ = '*';
263 *string++ = '.';
264 *string++ = '*';
265
266
267
268 for (mlen = 1; mlen <= maxmlen; mlen++)
269 {
270 if (mlen == 1 && *fmt == 'l')
271 length_modifier = long_modifier;
272 if (mlen == pDlen && strncmp (fmt, pD, pDlen) == 0)
273 length_modifier = pD_modifier;
274 if (mlen == pIlen && strncmp (fmt, pI, pIlen) == 0)
275 length_modifier = pI_modifier;
276 if (mlen == pMlen && strncmp (fmt, PRIdMAX, pMlen) == 0)
277 length_modifier = pM_modifier;
278 }
279
280
281
282 mlen = modifier_len[length_modifier];
283 string = mempcpy (string, fmt, mlen + 1);
284 fmt += mlen;
285 *string = 0;
286
287
288
289
290
291
292 ptrdiff_t size_bound = max (wid, prec) + SIZE_BOUND_EXTRA;
293
294
295 if (size_bound > size_allocated)
296 {
297 if (big_buffer)
298 xfree (big_buffer);
299 big_buffer = xmalloc (size_bound);
300 sprintf_buffer = big_buffer;
301 size_allocated = size_bound;
302 }
303 int minlen = 0;
304 ptrdiff_t tem;
305 switch (*fmt++)
306 {
307 default:
308 error ("Invalid format operation %s", fmt0);
309
310 case 'd':
311 switch (length_modifier)
312 {
313 case no_modifier:
314 {
315 int v = va_arg (ap, int);
316 tem = sprintf (sprintf_buffer, fmtstar, wid, prec, v);
317 }
318 break;
319 case long_modifier:
320 {
321 long v = va_arg (ap, long);
322 tem = sprintf (sprintf_buffer, fmtstar, wid, prec, v);
323 }
324 break;
325 case pD_modifier:
326 signed_pD_modifier:
327 {
328 ptrdiff_t v = va_arg (ap, ptrdiff_t);
329 tem = sprintf (sprintf_buffer, fmtstar, wid, prec, v);
330 }
331 break;
332 case pI_modifier:
333 {
334 EMACS_INT v = va_arg (ap, EMACS_INT);
335 tem = sprintf (sprintf_buffer, fmtstar, wid, prec, v);
336 }
337 break;
338 case pM_modifier:
339 {
340 intmax_t v = va_arg (ap, intmax_t);
341 tem = sprintf (sprintf_buffer, fmtstar, wid, prec, v);
342 }
343 break;
344 default:
345 eassume (false);
346 }
347
348 string = sprintf_buffer;
349 goto doit;
350
351 case 'o':
352 case 'x':
353 switch (length_modifier)
354 {
355 case no_modifier:
356 {
357 unsigned v = va_arg (ap, unsigned);
358 tem = sprintf (sprintf_buffer, fmtstar, wid, prec, v);
359 }
360 break;
361 case long_modifier:
362 {
363 unsigned long v = va_arg (ap, unsigned long);
364 tem = sprintf (sprintf_buffer, fmtstar, wid, prec, v);
365 }
366 break;
367 case pD_modifier:
368 goto signed_pD_modifier;
369 case pI_modifier:
370 {
371 EMACS_UINT v = va_arg (ap, EMACS_UINT);
372 tem = sprintf (sprintf_buffer, fmtstar, wid, prec, v);
373 }
374 break;
375 case pM_modifier:
376 {
377 uintmax_t v = va_arg (ap, uintmax_t);
378 tem = sprintf (sprintf_buffer, fmtstar, wid, prec, v);
379 }
380 break;
381 default:
382 eassume (false);
383 }
384
385 string = sprintf_buffer;
386 goto doit;
387
388 case 'f':
389 case 'e':
390 case 'g':
391 {
392 double d = va_arg (ap, double);
393 tem = sprintf (sprintf_buffer, fmtstar, wid, prec, d);
394
395 string = sprintf_buffer;
396 goto doit;
397 }
398
399 case 'S':
400 case 's':
401 minlen = minusflag ? -wid : wid;
402 string = va_arg (ap, char *);
403 tem = strnlen (string, STRING_BYTES_BOUND + 1);
404 if (tem == STRING_BYTES_BOUND + 1)
405 error ("String for %%s or %%S format is too long");
406 width = strwidth (string, tem);
407 goto doit1;
408
409
410 doit:
411 eassert (0 <= tem);
412
413 if (STRING_BYTES_BOUND < tem)
414 error ("Format width or precision too large");
415 width = tem;
416 doit1:
417
418
419
420
421 if (minlen > 0)
422 {
423 while (minlen > width && bufsize > 0)
424 {
425 *bufptr++ = ' ';
426 bufsize--;
427 minlen--;
428 }
429 minlen = 0;
430 }
431 if (tem > bufsize)
432 {
433
434 tem = bufsize;
435 do
436 {
437 tem--;
438 if (CHAR_HEAD_P (string[tem]))
439 {
440 if (BYTES_BY_CHAR_HEAD (string[tem]) <= bufsize - tem)
441 tem = bufsize;
442 break;
443 }
444 }
445 while (tem != 0);
446
447 memcpy (bufptr, string, tem);
448 bufptr[tem] = 0;
449
450
451
452 bufptr += bufsize;
453 bufsize = 0;
454 continue;
455 }
456 memcpy (bufptr, string, tem);
457 bufptr += tem;
458 bufsize -= tem;
459 if (minlen < 0)
460 {
461 while (minlen < - width && bufsize > 0)
462 {
463 *bufptr++ = ' ';
464 bufsize--;
465 minlen++;
466 }
467 minlen = 0;
468 }
469 continue;
470
471 case 'c':
472 {
473 int chr = va_arg (ap, int);
474 tem = CHAR_STRING (chr, (unsigned char *) charbuf);
475 string = charbuf;
476 string[tem] = 0;
477 width = strwidth (string, tem);
478 minlen = minusflag ? -wid : wid;
479 goto doit1;
480 }
481
482 case '%':
483
484 break;
485 }
486 }
487
488 char const *src;
489 ptrdiff_t srclen;
490 if (EQ (quoting_style, Qcurve) && fmtchar == '`')
491 src = uLSQM, srclen = sizeof uLSQM - 1;
492 else if (EQ (quoting_style, Qcurve) && fmtchar == '\'')
493 src = uRSQM, srclen = sizeof uRSQM - 1;
494 else if (! LEADING_CODE_P (fmtchar))
495 {
496 if (EQ (quoting_style, Qstraight) && fmtchar == '`')
497 fmtchar = '\'';
498
499 *bufptr++ = fmtchar;
500 continue;
501 }
502 else
503 {
504 int charlen = BYTES_BY_CHAR_HEAD (fmtchar);
505 src = fmt0;
506
507
508
509 for (srclen = 1 ; *(src + srclen) != 0 && srclen < charlen ; srclen++);
510
511 fmt = src + srclen;
512 }
513
514 if (bufsize < srclen)
515 {
516
517
518 do
519 *bufptr++ = '\0';
520 while (--bufsize != 0);
521 }
522 else
523 {
524 do
525 *bufptr++ = *src++;
526 while (--srclen != 0);
527 }
528 }
529
530
531 xfree (big_buffer);
532
533 *bufptr = 0;
534 return bufptr - buffer;
535 }
536
537
538
539
540
541
542
543
544
545 ptrdiff_t
546 esprintf (char *buf, char const *format, ...)
547 {
548 ptrdiff_t nbytes;
549 va_list ap;
550 va_start (ap, format);
551 nbytes = doprnt (buf, TYPE_MAXIMUM (ptrdiff_t), format, 0, ap);
552 va_end (ap);
553 return nbytes;
554 }
555
556 #if defined HAVE_X_WINDOWS && defined USE_X_TOOLKIT
557
558
559
560
561
562
563
564 ptrdiff_t
565 exprintf (char **buf, ptrdiff_t *bufsize,
566 char *nonheapbuf, ptrdiff_t bufsize_max,
567 char const *format, ...)
568 {
569 ptrdiff_t nbytes;
570 va_list ap;
571 va_start (ap, format);
572 nbytes = evxprintf (buf, bufsize, nonheapbuf, bufsize_max, format, ap);
573 va_end (ap);
574 return nbytes;
575 }
576
577 #endif
578
579
580 ptrdiff_t
581 evxprintf (char **buf, ptrdiff_t *bufsize,
582 char *nonheapbuf, ptrdiff_t bufsize_max,
583 char const *format, va_list ap)
584 {
585 for (;;)
586 {
587 ptrdiff_t nbytes;
588 va_list ap_copy;
589 va_copy (ap_copy, ap);
590 nbytes = doprnt (*buf, *bufsize, format, 0, ap_copy);
591 va_end (ap_copy);
592 if (nbytes < *bufsize - 1)
593 return nbytes;
594 if (*buf != nonheapbuf)
595 {
596 xfree (*buf);
597 *buf = NULL;
598 }
599 *buf = xpalloc (NULL, bufsize, 1, bufsize_max, 1);
600 }
601 }