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: #include <config.h>
26: #include <stdio.h>
27: #include <ctype.h>
28:
29: #ifdef STDC_HEADERS
30: #include <float.h>
31: #endif
32:
33: #ifdef HAVE_UNISTD_H
34: #include <unistd.h>
35: #endif
36:
37: #ifdef HAVE_STDLIB_H
38: #include <stdlib.h>
39: #endif
40:
41: #include "lisp.h"
42:
43: #ifndef DBL_MAX_10_EXP
44: #define DBL_MAX_10_EXP 308
45: #endif
46:
47:
48:
49:
50: #include "charset.h"
51:
52: static int doprnt1 ();
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64: int
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: {
73: return doprnt1 (0, buffer, bufsize, format, format_end, nargs, args);
74: }
75:
76:
77:
78:
79: int
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: {
101: int cnt = 0;
102: register char *fmt = format;
103: register char *bufptr = buffer;
104:
105:
106: char tembuf[DBL_MAX_10_EXP + 100];
107:
108:
109: unsigned size_allocated = sizeof (tembuf);
110:
111:
112: char *sprintf_buffer = tembuf;
113:
114:
115: char *big_buffer = 0;
116:
117: register int tem;
118: unsigned char *string;
119: char fixed_buffer[20];
120: char *fmtcpy;
121: int minlen;
122: unsigned char charbuf[5];
123:
124: if (format_end == 0)
125: format_end = format + strlen (format);
126:
127: if ((format_end - format + 1) < sizeof (fixed_buffer))
128: fmtcpy = fixed_buffer;
129: else
130: fmtcpy = (char *) alloca (format_end - format + 1);
131:
132: bufsize--;
133:
134:
135: while (fmt != format_end && bufsize > 0)
136: {
137: if (*fmt == '%')
138: {
139: unsigned size_bound = 0;
140: int width;
141:
142: fmt++;
143:
144: string = (unsigned char *) fmtcpy;
145: *string++ = '%';
146: while (1)
147: {
148: *string++ = *fmt;
149: if ('0' <= *fmt && *fmt <= '9')
150: {
151:
152:
153:
154:
155: unsigned n = *fmt - '0';
156: while ('0' <= fmt[1] && fmt[1] <= '9')
157: {
158: if (n * 10 / 10 != n
159: || (n = n * 10 + (fmt[1] - '0')) < n)
160: error ("Format width or precision too large");
161: *string++ = *++fmt;
162: }
163:
164: if (size_bound < n)
165: size_bound = n;
166: }
167: else if (*fmt == '-' || *fmt == ' ' || *fmt == '.' || *fmt == '+')
168: ;
169: else
170: break;
171: fmt++;
172: }
173: *string = 0;
174:
175:
176:
177: if (size_bound + DBL_MAX_10_EXP + 50 < size_bound)
178: error ("Format width or precision too large");
179: size_bound += DBL_MAX_10_EXP + 50;
180:
181:
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: }
191: minlen = 0;
192: switch (*fmt++)
193: {
194: default:
195: error ("Invalid format operation %%%c", fmt[-1]);
196:
197:
198: case 'd':
199: case 'o':
200: case 'x':
201: if (cnt == nargs)
202: error ("Not enough arguments for format string");
203: if (sizeof (int) == sizeof (EMACS_INT))
204: ;
205: else if (sizeof (long) == sizeof (EMACS_INT))
206:
207: string[1] = string[0],
208: string[0] = string[-1],
209: string[-1] = 'l',
210: string++;
211: else
212: abort ();
213: sprintf (sprintf_buffer, fmtcpy, args[cnt++]);
214:
215: string = (unsigned char *) sprintf_buffer;
216: goto doit;
217:
218: case 'f':
219: case 'e':
220: case 'g':
221: {
222: union { double d; char *half[2]; } u;
223: if (cnt + 1 == nargs)
224: error ("Not enough arguments for format string");
225: u.half[0] = args[cnt++];
226: u.half[1] = args[cnt++];
227: sprintf (sprintf_buffer, fmtcpy, u.d);
228:
229: string = (unsigned char *) sprintf_buffer;
230: goto doit;
231: }
232:
233: case 'S':
234: string[-1] = 's';
235: case 's':
236: if (cnt == nargs)
237: error ("Not enough arguments for format string");
238: if (fmtcpy[1] != 's')
239: minlen = atoi (&fmtcpy[1]);
240: if (lispstrings)
241: {
242: string = ((struct Lisp_String *) args[cnt])->data;
243: tem = STRING_BYTES ((struct Lisp_String *) args[cnt]);
244: cnt++;
245: }
246: else
247: {
248: string = (unsigned char *) args[cnt++];
249: tem = strlen (string);
250: }
251: width = strwidth (string, tem);
252: goto doit1;
253:
254:
255: doit:
256:
257: width = tem = strlen (string);
258: doit1:
259:
260:
261:
262:
263: if (minlen > 0)
264: {
265: while (minlen > width && bufsize > 0)
266: {
267: *bufptr++ = ' ';
268: bufsize--;
269: minlen--;
270: }
271: minlen = 0;
272: }
273: if (tem > bufsize)
274: {
275:
276: tem = bufsize;
277: while (!CHAR_HEAD_P (string[tem - 1])) tem--;
278: bcopy (string, bufptr, tem);
279:
280: width = strwidth (bufptr, tem);
281: }
282: else
283: bcopy (string, bufptr, tem);
284: bufptr += tem;
285: bufsize -= tem;
286: if (minlen < 0)
287: {
288: while (minlen < - width && bufsize > 0)
289: {
290: *bufptr++ = ' ';
291: bufsize--;
292: minlen++;
293: }
294: minlen = 0;
295: }
296: continue;
297:
298: case 'c':
299: if (cnt == nargs)
300: error ("Not enough arguments for format string");
301: tem = CHAR_STRING ((int) (EMACS_INT) args[cnt], charbuf);
302: string = charbuf;
303: cnt++;
304: string[tem] = 0;
305: width = strwidth (string, tem);
306: if (fmtcpy[1] != 'c')
307: minlen = atoi (&fmtcpy[1]);
308: goto doit1;
309:
310: case '%':
311: fmt--;
312: }
313: }
314:
315: {
316:
317:
318: char *save_bufptr = bufptr;
319:
320: do { *bufptr++ = *fmt++; }
321: while (--bufsize > 0 && !CHAR_HEAD_P (*fmt));
322: if (!CHAR_HEAD_P (*fmt))
323: {
324: bufptr = save_bufptr;
325: break;
326: }
327: }
328: };
329:
330:
331: if (big_buffer)
332: xfree (big_buffer);
333:
334: *bufptr = 0;
335: return bufptr - buffer;
336: }
337:
338:
339: