]> code.delx.au - gnu-emacs/blob - src/doprnt.c
Merge from mainline.
[gnu-emacs] / src / doprnt.c
1 /* Output like sprintf to a buffer of specified size.
2 Also takes args differently: pass one pointer to the end
3 of the format string in addition to the format string itself.
4 Copyright (C) 1985, 2001-2011 Free Software Foundation, Inc.
5
6 This file is part of GNU Emacs.
7
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
20
21 /* If you think about replacing this with some similar standard C function of
22 the printf family (such as vsnprintf), please note that this function
23 supports the following Emacs-specific features:
24
25 . For %c conversions, it produces a string with the multibyte representation
26 of the (`int') argument, suitable for display in an Emacs buffer.
27
28 . For %s and %c, when field width is specified (e.g., %25s), it accounts for
29 the diplay width of each character, according to char-width-table. That
30 is, it does not assume that each character takes one column on display.
31
32 . If the size of the buffer is not enough to produce the formatted string in
33 its entirety, it makes sure that truncation does not chop the last
34 character in the middle of its multibyte sequence, producing an invalid
35 sequence.
36
37 . It accepts a pointer to the end of the format string, so the format string
38 could include embedded null characters.
39
40 . It signals an error if the length of the formatted string is about to
41 overflow MOST_POSITIVE_FIXNUM, to avoid producing strings longer than what
42 Emacs can handle.
43
44 OTOH, this function supports only a small subset of the standard C formatted
45 output facilities. E.g., %u and %ll are not supported, and precision is
46 ignored %s and %c conversions. (See below for the detailed documentation of
47 what is supported.) However, this is okay, as this function is supposed to
48 be called from `error' and similar functions, and thus does not need to
49 support features beyond those in `Fformat', which is used by `error' on the
50 Lisp level. */
51
52 /* This function supports the following %-sequences in the `format'
53 argument:
54
55 %s means print a string argument.
56 %S is silently treated as %s, for loose compatibility with `Fformat'.
57 %d means print a `signed int' argument in decimal.
58 %l means print a `long int' argument in decimal.
59 %o means print an `unsigned int' argument in octal.
60 %x means print an `unsigned int' argument in hex.
61 %e means print a `double' argument in exponential notation.
62 %f means print a `double' argument in decimal-point notation.
63 %g means print a `double' argument in exponential notation
64 or in decimal-point notation, whichever uses fewer characters.
65 %c means print a `signed int' argument as a single character.
66 %% means produce a literal % character.
67
68 A %-sequence may contain optional flag, width, and precision specifiers, as
69 follows:
70
71 %<flags><width><precision>character
72
73 where flags is [+ -0l], width is [0-9]+, and precision is .[0-9]+
74
75 The + flag character inserts a + before any positive number, while a space
76 inserts a space before any positive number; these flags only affect %d, %l,
77 %o, %x, %e, %f, and %g sequences. The - and 0 flags affect the width
78 specifier, as described below.
79
80 The l (lower-case letter ell) flag is a `long' data type modifier: it is
81 supported for %d, %o, and %x conversions of integral arguments, and means
82 that the respective argument is to be treated as `long int' or `unsigned
83 long int'. The EMACS_INT data type should use this modifier.
84
85 The width specifier supplies a lower limit for the length of the printed
86 representation. The padding, if any, normally goes on the left, but it goes
87 on the right if the - flag is present. The padding character is normally a
88 space, but (for numerical arguments only) it is 0 if the 0 flag is present.
89 The - flag takes precedence over the 0 flag.
90
91 For %e, %f, and %g sequences, the number after the "." in the precision
92 specifier says how many decimal places to show; if zero, the decimal point
93 itself is omitted. For %s and %S, the precision specifier is ignored. */
94
95 #include <config.h>
96 #include <stdio.h>
97 #include <ctype.h>
98 #include <setjmp.h>
99
100 #ifdef STDC_HEADERS
101 #include <float.h>
102 #endif
103
104 #include <unistd.h>
105
106 #include <limits.h>
107 #ifndef SIZE_MAX
108 # define SIZE_MAX ((size_t) -1)
109 #endif
110
111 #include "lisp.h"
112
113 /* Since we use the macro CHAR_HEAD_P, we have to include this, but
114 don't have to include others because CHAR_HEAD_P does not contains
115 another macro. */
116 #include "character.h"
117
118 #ifndef DBL_MAX_10_EXP
119 #define DBL_MAX_10_EXP 308 /* IEEE double */
120 #endif
121
122 /* Generate output from a format-spec FORMAT,
123 terminated at position FORMAT_END.
124 Output goes in BUFFER, which has room for BUFSIZE chars.
125 If the output does not fit, truncate it to fit.
126 Returns the number of bytes stored into BUFFER, excluding
127 the terminating null byte. Output is always null-terminated.
128 String arguments are passed as C strings.
129 Integers are passed as C integers. */
130
131 size_t
132 doprnt (char *buffer, register size_t bufsize, const char *format,
133 const char *format_end, va_list ap)
134 {
135 const char *fmt = format; /* Pointer into format string */
136 register char *bufptr = buffer; /* Pointer into output buffer.. */
137
138 /* Use this for sprintf unless we need something really big. */
139 char tembuf[DBL_MAX_10_EXP + 100];
140
141 /* Size of sprintf_buffer. */
142 size_t size_allocated = sizeof (tembuf);
143
144 /* Buffer to use for sprintf. Either tembuf or same as BIG_BUFFER. */
145 char *sprintf_buffer = tembuf;
146
147 /* Buffer we have got with malloc. */
148 char *big_buffer = NULL;
149
150 register size_t tem;
151 char *string;
152 char fixed_buffer[20]; /* Default buffer for small formatting. */
153 char *fmtcpy;
154 int minlen;
155 char charbuf[MAX_MULTIBYTE_LENGTH + 1]; /* Used for %c. */
156 USE_SAFE_ALLOCA;
157
158 if (format_end == 0)
159 format_end = format + strlen (format);
160
161 if ((format_end - format + 1) < sizeof (fixed_buffer))
162 fmtcpy = fixed_buffer;
163 else
164 SAFE_ALLOCA (fmtcpy, char *, format_end - format + 1);
165
166 bufsize--;
167
168 /* Loop until end of format string or buffer full. */
169 while (fmt != format_end && bufsize > 0)
170 {
171 if (*fmt == '%') /* Check for a '%' character */
172 {
173 size_t size_bound = 0;
174 EMACS_INT width; /* Columns occupied by STRING on display. */
175 int long_flag = 0;
176
177 fmt++;
178 /* Copy this one %-spec into fmtcpy. */
179 string = fmtcpy;
180 *string++ = '%';
181 while (1)
182 {
183 *string++ = *fmt;
184 if ('0' <= *fmt && *fmt <= '9')
185 {
186 /* Get an idea of how much space we might need.
187 This might be a field width or a precision; e.g.
188 %1.1000f and %1000.1f both might need 1000+ bytes.
189 Parse the width or precision, checking for overflow. */
190 size_t n = *fmt - '0';
191 while ('0' <= fmt[1] && fmt[1] <= '9')
192 {
193 if (n >= SIZE_MAX / 10
194 || n * 10 > SIZE_MAX - (fmt[1] - '0'))
195 error ("Format width or precision too large");
196 n = n * 10 + fmt[1] - '0';
197 *string++ = *++fmt;
198 }
199
200 if (size_bound < n)
201 size_bound = n;
202 }
203 else if (*fmt == '-' || *fmt == ' ' || *fmt == '.' || *fmt == '+')
204 ;
205 else if (*fmt == 'l')
206 {
207 long_flag = 1;
208 if (!strchr ("dox", fmt[1]))
209 /* %l as conversion specifier, not as modifier. */
210 break;
211 }
212 else
213 break;
214 fmt++;
215 }
216 *string = 0;
217
218 /* Make the size bound large enough to handle floating point formats
219 with large numbers. */
220 if (size_bound > SIZE_MAX - DBL_MAX_10_EXP - 50)
221 error ("Format width or precision too large");
222 size_bound += DBL_MAX_10_EXP + 50;
223
224 /* Make sure we have that much. */
225 if (size_bound > size_allocated)
226 {
227 if (big_buffer)
228 big_buffer = (char *) xrealloc (big_buffer, size_bound);
229 else
230 big_buffer = (char *) xmalloc (size_bound);
231 sprintf_buffer = big_buffer;
232 size_allocated = size_bound;
233 }
234 minlen = 0;
235 switch (*fmt++)
236 {
237 default:
238 error ("Invalid format operation %%%c", fmt[-1]);
239
240 /* case 'b': */
241 case 'l':
242 case 'd':
243 {
244 int i;
245 long l;
246
247 if (long_flag)
248 {
249 l = va_arg(ap, long);
250 sprintf (sprintf_buffer, fmtcpy, l);
251 }
252 else
253 {
254 i = va_arg(ap, int);
255 sprintf (sprintf_buffer, fmtcpy, i);
256 }
257 /* Now copy into final output, truncating as necessary. */
258 string = sprintf_buffer;
259 goto doit;
260 }
261
262 case 'o':
263 case 'x':
264 {
265 unsigned u;
266 unsigned long ul;
267
268 if (long_flag)
269 {
270 ul = va_arg(ap, unsigned long);
271 sprintf (sprintf_buffer, fmtcpy, ul);
272 }
273 else
274 {
275 u = va_arg(ap, unsigned);
276 sprintf (sprintf_buffer, fmtcpy, u);
277 }
278 /* Now copy into final output, truncating as necessary. */
279 string = sprintf_buffer;
280 goto doit;
281 }
282
283 case 'f':
284 case 'e':
285 case 'g':
286 {
287 double d = va_arg(ap, double);
288 sprintf (sprintf_buffer, fmtcpy, d);
289 /* Now copy into final output, truncating as necessary. */
290 string = sprintf_buffer;
291 goto doit;
292 }
293
294 case 'S':
295 string[-1] = 's';
296 case 's':
297 if (fmtcpy[1] != 's')
298 minlen = atoi (&fmtcpy[1]);
299 string = va_arg (ap, char *);
300 tem = strlen (string);
301 if (tem > MOST_POSITIVE_FIXNUM)
302 error ("String for %%s or %%S format is too long");
303 width = strwidth (string, tem);
304 goto doit1;
305
306 /* Copy string into final output, truncating if no room. */
307 doit:
308 /* Coming here means STRING contains ASCII only. */
309 tem = strlen (string);
310 if (tem > MOST_POSITIVE_FIXNUM)
311 error ("Format width or precision too large");
312 width = tem;
313 doit1:
314 /* We have already calculated:
315 TEM -- length of STRING,
316 WIDTH -- columns occupied by STRING when displayed, and
317 MINLEN -- minimum columns of the output. */
318 if (minlen > 0)
319 {
320 while (minlen > width && bufsize > 0)
321 {
322 *bufptr++ = ' ';
323 bufsize--;
324 minlen--;
325 }
326 minlen = 0;
327 }
328 if (tem > bufsize)
329 {
330 /* Truncate the string at character boundary. */
331 tem = bufsize;
332 while (!CHAR_HEAD_P (string[tem - 1])) tem--;
333 memcpy (bufptr, string, tem);
334 /* We must calculate WIDTH again. */
335 width = strwidth (bufptr, tem);
336 }
337 else
338 memcpy (bufptr, string, tem);
339 bufptr += tem;
340 bufsize -= tem;
341 if (minlen < 0)
342 {
343 while (minlen < - width && bufsize > 0)
344 {
345 *bufptr++ = ' ';
346 bufsize--;
347 minlen++;
348 }
349 minlen = 0;
350 }
351 continue;
352
353 case 'c':
354 {
355 int chr = va_arg(ap, int);
356 tem = CHAR_STRING (chr, (unsigned char *) charbuf);
357 string = charbuf;
358 string[tem] = 0;
359 width = strwidth (string, tem);
360 if (fmtcpy[1] != 'c')
361 minlen = atoi (&fmtcpy[1]);
362 goto doit1;
363 }
364
365 case '%':
366 fmt--; /* Drop thru and this % will be treated as normal */
367 }
368 }
369
370 {
371 /* Just some character; Copy it if the whole multi-byte form
372 fit in the buffer. */
373 char *save_bufptr = bufptr;
374
375 do { *bufptr++ = *fmt++; }
376 while (--bufsize > 0 && !CHAR_HEAD_P (*fmt));
377 if (!CHAR_HEAD_P (*fmt))
378 {
379 bufptr = save_bufptr;
380 break;
381 }
382 }
383 };
384
385 /* If we had to malloc something, free it. */
386 xfree (big_buffer);
387
388 *bufptr = 0; /* Make sure our string ends with a '\0' */
389
390 SAFE_FREE ();
391 return bufptr - buffer;
392 }