49
|
1 /* Output like sprintf to a buffer of specified size.
|
|
2 Also takes args differently: pass one pointer to an array of strings
|
|
3 in addition to the format string which is separate.
|
75227
|
4 Copyright (C) 1985, 2001, 2002, 2003, 2004, 2005,
|
|
5 2006, 2007 Free Software Foundation, Inc.
|
49
|
6
|
|
7 This file is part of GNU Emacs.
|
|
8
|
|
9 GNU Emacs is free software; you can redistribute it and/or modify
|
|
10 it under the terms of the GNU General Public License as published by
|
78260
|
11 the Free Software Foundation; either version 3, or (at your option)
|
49
|
12 any later version.
|
|
13
|
|
14 GNU Emacs is distributed in the hope that it will be useful,
|
|
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17 GNU General Public License for more details.
|
|
18
|
|
19 You should have received a copy of the GNU General Public License
|
|
20 along with GNU Emacs; see the file COPYING. If not, write to
|
64084
|
21 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
22 Boston, MA 02110-1301, USA. */
|
49
|
23
|
|
24
|
5036
|
25 #include <config.h>
|
49
|
26 #include <stdio.h>
|
|
27 #include <ctype.h>
|
|
28
|
18681
|
29 #ifdef STDC_HEADERS
|
16943
|
30 #include <float.h>
|
|
31 #endif
|
|
32
|
25323
|
33 #ifdef HAVE_UNISTD_H
|
|
34 #include <unistd.h>
|
|
35 #endif
|
|
36
|
|
37 #ifdef HAVE_STDLIB_H
|
|
38 #include <stdlib.h>
|
|
39 #endif
|
|
40
|
18627
|
41 #include "lisp.h"
|
|
42
|
16943
|
43 #ifndef DBL_MAX_10_EXP
|
|
44 #define DBL_MAX_10_EXP 308 /* IEEE double */
|
|
45 #endif
|
|
46
|
17030
|
47 /* Since we use the macro CHAR_HEAD_P, we have to include this, but
|
|
48 don't have to include others because CHAR_HEAD_P does not contains
|
|
49 another macro. */
|
|
50 #include "charset.h"
|
|
51
|
13449
|
52 static int doprnt1 ();
|
|
53
|
147
|
54 /* Generate output from a format-spec FORMAT,
|
|
55 terminated at position FORMAT_END.
|
|
56 Output goes in BUFFER, which has room for BUFSIZE chars.
|
|
57 If the output does not fit, truncate it to fit.
|
49442
|
58 Returns the number of bytes stored into BUFFER.
|
147
|
59 ARGS points to the vector of arguments, and NARGS says how many.
|
13449
|
60 A double counts as two arguments.
|
|
61 String arguments are passed as C strings.
|
|
62 Integers are passed as C integers. */
|
147
|
63
|
21514
|
64 int
|
49
|
65 doprnt (buffer, bufsize, format, format_end, nargs, args)
|
|
66 char *buffer;
|
|
67 register int bufsize;
|
|
68 char *format;
|
|
69 char *format_end;
|
|
70 int nargs;
|
|
71 char **args;
|
|
72 {
|
13449
|
73 return doprnt1 (0, buffer, bufsize, format, format_end, nargs, args);
|
|
74 }
|
|
75
|
|
76 /* Like doprnt except that strings in ARGS are passed
|
|
77 as Lisp_Object. */
|
|
78
|
21514
|
79 int
|
13449
|
80 doprnt_lisp (buffer, bufsize, format, format_end, nargs, args)
|
|
81 char *buffer;
|
|
82 register int bufsize;
|
|
83 char *format;
|
|
84 char *format_end;
|
|
85 int nargs;
|
|
86 char **args;
|
|
87 {
|
|
88 return doprnt1 (1, buffer, bufsize, format, format_end, nargs, args);
|
|
89 }
|
|
90
|
|
91 static int
|
|
92 doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args)
|
|
93 int lispstrings;
|
|
94 char *buffer;
|
|
95 register int bufsize;
|
|
96 char *format;
|
|
97 char *format_end;
|
|
98 int nargs;
|
|
99 char **args;
|
|
100 {
|
49
|
101 int cnt = 0; /* Number of arg to gobble next */
|
|
102 register char *fmt = format; /* Pointer into format string */
|
|
103 register char *bufptr = buffer; /* Pointer into output buffer.. */
|
4774
|
104
|
147
|
105 /* Use this for sprintf unless we need something really big. */
|
16943
|
106 char tembuf[DBL_MAX_10_EXP + 100];
|
4774
|
107
|
147
|
108 /* Size of sprintf_buffer. */
|
75950
|
109 unsigned size_allocated = sizeof (tembuf);
|
4774
|
110
|
147
|
111 /* Buffer to use for sprintf. Either tembuf or same as BIG_BUFFER. */
|
|
112 char *sprintf_buffer = tembuf;
|
4774
|
113
|
147
|
114 /* Buffer we have got with malloc. */
|
|
115 char *big_buffer = 0;
|
4774
|
116
|
49
|
117 register int tem;
|
22310
|
118 unsigned char *string;
|
4774
|
119 char fixed_buffer[20]; /* Default buffer for small formatting. */
|
|
120 char *fmtcpy;
|
49
|
121 int minlen;
|
20310
|
122 unsigned char charbuf[5]; /* Used for %c. */
|
49
|
123
|
|
124 if (format_end == 0)
|
|
125 format_end = format + strlen (format);
|
|
126
|
4774
|
127 if ((format_end - format + 1) < sizeof (fixed_buffer))
|
|
128 fmtcpy = fixed_buffer;
|
|
129 else
|
5053
|
130 fmtcpy = (char *) alloca (format_end - format + 1);
|
4774
|
131
|
49
|
132 bufsize--;
|
4774
|
133
|
|
134 /* Loop until end of format string or buffer full. */
|
|
135 while (fmt != format_end && bufsize > 0)
|
49
|
136 {
|
|
137 if (*fmt == '%') /* Check for a '%' character */
|
|
138 {
|
75950
|
139 unsigned size_bound = 0;
|
17030
|
140 int width; /* Columns occupied by STRING. */
|
147
|
141
|
49
|
142 fmt++;
|
484
|
143 /* Copy this one %-spec into fmtcpy. */
|
75950
|
144 string = (unsigned char *) fmtcpy;
|
49
|
145 *string++ = '%';
|
4774
|
146 while (1)
|
49
|
147 {
|
|
148 *string++ = *fmt;
|
16943
|
149 if ('0' <= *fmt && *fmt <= '9')
|
|
150 {
|
|
151 /* Get an idea of how much space we might need.
|
|
152 This might be a field width or a precision; e.g.
|
|
153 %1.1000f and %1000.1f both might need 1000+ bytes.
|
|
154 Parse the width or precision, checking for overflow. */
|
75950
|
155 unsigned n = *fmt - '0';
|
16943
|
156 while ('0' <= fmt[1] && fmt[1] <= '9')
|
|
157 {
|
|
158 if (n * 10 / 10 != n
|
75950
|
159 || (n = n * 10 + (fmt[1] - '0')) < n)
|
16943
|
160 error ("Format width or precision too large");
|
|
161 *string++ = *++fmt;
|
|
162 }
|
|
163
|
|
164 if (size_bound < n)
|
|
165 size_bound = n;
|
|
166 }
|
75950
|
167 else if (*fmt == '-' || *fmt == ' ' || *fmt == '.' || *fmt == '+')
|
16943
|
168 ;
|
|
169 else
|
49
|
170 break;
|
|
171 fmt++;
|
|
172 }
|
|
173 *string = 0;
|
4774
|
174
|
16943
|
175 /* Make the size bound large enough to handle floating point formats
|
|
176 with large numbers. */
|
75950
|
177 if (size_bound + DBL_MAX_10_EXP + 50 < size_bound)
|
|
178 error ("Format width or precision too large");
|
16943
|
179 size_bound += DBL_MAX_10_EXP + 50;
|
|
180
|
147
|
181 /* Make sure we have that much. */
|
|
182 if (size_bound > size_allocated)
|
|
183 {
|
|
184 if (big_buffer)
|
|
185 big_buffer = (char *) xrealloc (big_buffer, size_bound);
|
|
186 else
|
|
187 big_buffer = (char *) xmalloc (size_bound);
|
|
188 sprintf_buffer = big_buffer;
|
|
189 size_allocated = size_bound;
|
|
190 }
|
49
|
191 minlen = 0;
|
|
192 switch (*fmt++)
|
|
193 {
|
|
194 default:
|
|
195 error ("Invalid format operation %%%c", fmt[-1]);
|
|
196
|
|
197 /* case 'b': */
|
|
198 case 'd':
|
|
199 case 'o':
|
|
200 case 'x':
|
|
201 if (cnt == nargs)
|
12797
|
202 error ("Not enough arguments for format string");
|
11700
|
203 if (sizeof (int) == sizeof (EMACS_INT))
|
|
204 ;
|
|
205 else if (sizeof (long) == sizeof (EMACS_INT))
|
|
206 /* Insert an `l' the right place. */
|
|
207 string[1] = string[0],
|
|
208 string[0] = string[-1],
|
|
209 string[-1] = 'l',
|
|
210 string++;
|
|
211 else
|
|
212 abort ();
|
147
|
213 sprintf (sprintf_buffer, fmtcpy, args[cnt++]);
|
|
214 /* Now copy into final output, truncating as nec. */
|
75950
|
215 string = (unsigned char *) sprintf_buffer;
|
49
|
216 goto doit;
|
|
217
|
147
|
218 case 'f':
|
|
219 case 'e':
|
|
220 case 'g':
|
|
221 {
|
|
222 union { double d; char *half[2]; } u;
|
|
223 if (cnt + 1 == nargs)
|
42859
|
224 error ("Not enough arguments for format string");
|
147
|
225 u.half[0] = args[cnt++];
|
|
226 u.half[1] = args[cnt++];
|
|
227 sprintf (sprintf_buffer, fmtcpy, u.d);
|
|
228 /* Now copy into final output, truncating as nec. */
|
75950
|
229 string = (unsigned char *) sprintf_buffer;
|
147
|
230 goto doit;
|
|
231 }
|
|
232
|
49
|
233 case 'S':
|
|
234 string[-1] = 's';
|
|
235 case 's':
|
|
236 if (cnt == nargs)
|
42859
|
237 error ("Not enough arguments for format string");
|
49
|
238 if (fmtcpy[1] != 's')
|
|
239 minlen = atoi (&fmtcpy[1]);
|
13449
|
240 if (lispstrings)
|
|
241 {
|
75950
|
242 string = ((struct Lisp_String *) args[cnt])->data;
|
|
243 tem = STRING_BYTES ((struct Lisp_String *) args[cnt]);
|
13449
|
244 cnt++;
|
|
245 }
|
|
246 else
|
|
247 {
|
75950
|
248 string = (unsigned char *) args[cnt++];
|
13449
|
249 tem = strlen (string);
|
|
250 }
|
17030
|
251 width = strwidth (string, tem);
|
13449
|
252 goto doit1;
|
|
253
|
49
|
254 /* Copy string into final output, truncating if no room. */
|
|
255 doit:
|
17030
|
256 /* Coming here means STRING contains ASCII only. */
|
|
257 width = tem = strlen (string);
|
8141
|
258 doit1:
|
17030
|
259 /* We have already calculated:
|
|
260 TEM -- length of STRING,
|
|
261 WIDTH -- columns occupied by STRING when displayed, and
|
|
262 MINLEN -- minimum columns of the output. */
|
49
|
263 if (minlen > 0)
|
|
264 {
|
17030
|
265 while (minlen > width && bufsize > 0)
|
49
|
266 {
|
|
267 *bufptr++ = ' ';
|
|
268 bufsize--;
|
|
269 minlen--;
|
|
270 }
|
|
271 minlen = 0;
|
|
272 }
|
|
273 if (tem > bufsize)
|
17030
|
274 {
|
|
275 /* Truncate the string at character boundary. */
|
|
276 tem = bufsize;
|
20530
|
277 while (!CHAR_HEAD_P (string[tem - 1])) tem--;
|
17030
|
278 bcopy (string, bufptr, tem);
|
|
279 /* We must calculate WIDTH again. */
|
|
280 width = strwidth (bufptr, tem);
|
|
281 }
|
|
282 else
|
|
283 bcopy (string, bufptr, tem);
|
49
|
284 bufptr += tem;
|
|
285 bufsize -= tem;
|
|
286 if (minlen < 0)
|
|
287 {
|
17030
|
288 while (minlen < - width && bufsize > 0)
|
49
|
289 {
|
|
290 *bufptr++ = ' ';
|
|
291 bufsize--;
|
|
292 minlen++;
|
|
293 }
|
|
294 minlen = 0;
|
|
295 }
|
|
296 continue;
|
|
297
|
|
298 case 'c':
|
|
299 if (cnt == nargs)
|
42859
|
300 error ("Not enough arguments for format string");
|
26852
|
301 tem = CHAR_STRING ((int) (EMACS_INT) args[cnt], charbuf);
|
|
302 string = charbuf;
|
17030
|
303 cnt++;
|
|
304 string[tem] = 0;
|
|
305 width = strwidth (string, tem);
|
8141
|
306 if (fmtcpy[1] != 'c')
|
|
307 minlen = atoi (&fmtcpy[1]);
|
|
308 goto doit1;
|
49
|
309
|
|
310 case '%':
|
|
311 fmt--; /* Drop thru and this % will be treated as normal */
|
|
312 }
|
|
313 }
|
17030
|
314
|
|
315 {
|
|
316 /* Just some character; Copy it if the whole multi-byte form
|
|
317 fit in the buffer. */
|
|
318 char *save_bufptr = bufptr;
|
|
319
|
|
320 do { *bufptr++ = *fmt++; }
|
20530
|
321 while (--bufsize > 0 && !CHAR_HEAD_P (*fmt));
|
|
322 if (!CHAR_HEAD_P (*fmt))
|
17030
|
323 {
|
|
324 bufptr = save_bufptr;
|
|
325 break;
|
|
326 }
|
|
327 }
|
49
|
328 };
|
|
329
|
147
|
330 /* If we had to malloc something, free it. */
|
|
331 if (big_buffer)
|
2439
|
332 xfree (big_buffer);
|
147
|
333
|
49
|
334 *bufptr = 0; /* Make sure our string end with a '\0' */
|
|
335 return bufptr - buffer;
|
|
336 }
|
52401
|
337
|
|
338 /* arch-tag: aa0ab528-7c5f-4c73-894c-aa2526a1efb3
|
|
339 (do not change this comment) */
|