1 #line 982 "../../src/builtin/snarf.m4"
2 /* -*- buffer-read-only: t -*- vi: set ro:
3    THIS FILE IS GENERATED AUTOMATICALLY.  PLEASE DO NOT EDIT.
4 */
5 #line 982
6 #ifdef HAVE_CONFIG_H
7 #line 982
8 # include <config.h>
9 #line 982
10 #endif
11 #line 982
12 #include <sys/types.h>
13 #line 982
14 
15 #line 982
16 #include "mailfromd.h"
17 #line 982
18 #include "prog.h"
19 #line 982
20 #include "builtin.h"
21 #line 982
22 
23 #line 982
24 
25 #line 1022 "../../src/builtin/snarf.m4"
26 
27 /* End of snarf.m4 */
28 #line 1 "sprintf.bi"
29 /* This file is part of Mailfromd.             -*- c -*-
30    Copyright (C) 2007-2021 Sergey Poznyakoff
31 
32    This program is free software; you can redistribute it and/or modify
33    it under the terms of the GNU General Public License as published by
34    the Free Software Foundation; either version 3, or (at your option)
35    any later version.
36 
37    This program is distributed in the hope that it will be useful,
38    but WITHOUT ANY WARRANTY; without even the implied warranty of
39    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
40    GNU General Public License for more details.
41 
42    You should have received a copy of the GNU General Public License
43    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
44 
45 
46 
47 #define FMT_ALTPOS         0x01
48 #define FMT_ALTERNATE      0x02
49 #define FMT_PADZERO        0x04
50 #define FMT_ADJUST_LEFT    0x08
51 #define FMT_SPACEPFX       0x10
52 #define FMT_SIGNPFX        0x20
53 
54 typedef enum {
55 	fmts_copy,      /* Copy char as is */
56 	fmts_pos,       /* Expect argument position -- %_2$ */
57 	fmts_flags,     /* Expect flags -- %2$_# */
58 	fmts_width,     /* Expect width -- %2$#_8 or %2$#_* */
59 	fmts_width_arg, /* Expect width argument position -- %2$#*_1$ */
60 	fmts_prec,      /* Expect precision */
61 	fmts_prec_arg,  /* Expect precision argument position */
62 	fmts_conv       /* Expect conversion specifier */
63 } printf_format_state;
64 
65 static int
get_num(const char * p,int i,unsigned * pn)66 get_num(const char *p, int i, unsigned *pn)
67 {
68 	unsigned n = 0;
69 
70 	for (; p[i] && mu_isdigit(p[i]); i++)
71 		n = n * 10 + p[i] - '0';
72 	*pn = n;
73 	return i;
74 }
75 
76 #define __MF_MAX(a,b) ((a)>(b) ? (a) : (b))
77 #define SPRINTF_BUF_SIZE (__MF_MAX(3*sizeof(long), NUMERIC_BUFSIZE_BOUND) + 2)
78 
79 void
80 #line 51
bi_sprintf(eval_environ_t env)81 bi_sprintf(eval_environ_t env)
82 #line 51
83 
84 #line 51
85 
86 #line 51 "sprintf.bi"
87 {
88 #line 51
89 
90 #line 51
91 
92 #line 51
93 long __bi_argcnt;
94 #line 51
95 char * MFL_DATASEG format;
96 #line 51
97 
98 #line 51
99 get_string_arg(env, 1, &format);
100 #line 51
101 
102 #line 51
103 get_numeric_arg(env, 0, &__bi_argcnt);
104 #line 51
105         adjust_stack(env, __bi_argcnt + 1);
106 #line 51
107 
108 #line 51
109 
110 #line 51
111 	if (builtin_module_trace(BUILTIN_IDX_sprintf))
112 #line 51
113 		prog_trace(env, "sprintf %s",format);;
114 #line 51
115 
116 {
117 	int i = 0;
118 	int cur = 0;
119 	int start;
120 	char buf[SPRINTF_BUF_SIZE];
121 	printf_format_state state = fmts_copy;
122 	int flags = 0;
123 	unsigned width = 0;
124 	unsigned prec = 0;
125 	unsigned argnum;
126 
127 	heap_obstack_begin(env);
128 
129 #line 64
130 unroll_stack(env, __bi_argcnt + 1);
131 	while (format[cur]) {
132 		unsigned n;
133 		char *str;
134 		long num;
135 		int negative;
136 		char fmtbuf[] = { '%', 'x', 0 };
137 
138 		switch (state) {
139 		case fmts_copy:
140 			/* Expect `%', and copy all the rest verbatim */
141 			if (format[cur] == '%') {
142 				start = cur;
143 				state = fmts_pos;
144 				flags = 0;
145 				width = 0;
146 				prec = 0;
147 			} else
148 				do { char __c = format[cur]; heap_obstack_grow(env, &__c, 1); } while(0);
149 			cur++;
150 			break;
151 
152 		case fmts_pos:
153 			/* Expect '%' or an argument position -- %_% or %_2$ */
154 			if (format[cur] == '%') {
155 				do { char __c = '%'; heap_obstack_grow(env, &__c, 1); } while(0);
156 				cur++;
157 				state = fmts_copy;
158 				break;
159 			}
160 			if (mu_isdigit(format[cur])) {
161 				int pos = get_num(format, cur, &n);
162 				if (format[pos] == '$') {
163 					argnum = n - 1;
164 					flags |= FMT_ALTPOS;
165 					cur = pos + 1;
166 				}
167 			}
168 			state = fmts_flags;
169 			break;
170 
171 		case fmts_flags:
172 			/* Expect flags -- %2$_# */
173 			switch (format[cur]) {
174 			case '#':
175 				flags |= FMT_ALTERNATE;
176 				cur++;
177 				break;
178 
179 			case '0':
180 				flags |= FMT_PADZERO;
181 				cur++;
182 				break;
183 
184 			case '-':
185 				flags |= FMT_ADJUST_LEFT;
186 				cur++;
187 				break;
188 
189 			case ' ':
190 				flags |= FMT_SPACEPFX;
191 				cur++;
192 				break;
193 
194 			case '+':
195 				flags |= FMT_SIGNPFX;
196 				cur++;
197 				break;
198 
199 			default:
200 				state = fmts_width;
201 			}
202 			break;
203 
204 		case fmts_width:
205 			/* Expect width -- %2$#_8 or %2$#_* */
206 			if (mu_isdigit(format[cur])) {
207 				cur = get_num(format, cur, &width);
208 				state = fmts_prec;
209 			} else if (format[cur] == '*') {
210 				cur++;
211 				state = fmts_width_arg;
212 			} else
213 				state = fmts_prec;
214 			break;
215 
216 		case fmts_width_arg:
217 			/* Expect width argument position -- %2$#*_1$ */
218 			state = fmts_prec;
219 			if (mu_isdigit(format[cur])) {
220 				int pos = get_num(format, cur, &n);
221 				if (format[pos] == '$') {
222 
223 #line 156
224  ((__bi_argcnt > (n-1+1)) ?   get_numeric_arg(env, (n-1+1) + 1, &num) :   ((
225 #line 156
226 	env_throw_bi(env, mfe_range, "sprintf", "Argument %u is not supplied",(unsigned) (n-1+1))
227 #line 156
228 ),(long ) 0));
229 					cur = pos + 1;
230 					if (num < 0) {
231 						flags |= FMT_SPACEPFX;
232 						num = - num;
233 					}
234 					width = (unsigned) num;
235 					break;
236 				}
237 			}
238 
239 #line 166
240  ((__bi_argcnt > (i+1)) ?   get_numeric_arg(env, (i+1) + 1, &num) :   ((
241 #line 166
242 	env_throw_bi(env, mfe_range, "sprintf", "Argument %u is not supplied",(unsigned) (i+1))
243 #line 166
244 ),(long ) 0));
245 			i++;
246 			if (num < 0) {
247 				/* A negative field width is taken
248 				   as a `-' flag followed by a positive field width. */
249 				flags |= FMT_SPACEPFX;
250 				num = - num;
251 			}
252 			width = (unsigned) num;
253 			break;
254 
255 		case fmts_prec:
256 			/* Expect precision -- %2$#*1$_. */
257 			state = fmts_conv;
258 			if (format[cur] == '.') {
259 				cur++;
260 				if (mu_isdigit(format[cur])) {
261 					cur = get_num(format, cur, &prec);
262 				} else if (format[cur] == '*') {
263 					cur++;
264 					state = fmts_prec_arg;
265 				}
266 			}
267 			break;
268 
269 		case fmts_prec_arg:
270                         /* Expect precision argument position --
271 			                %2$#*1$.*_3$ */
272 			state = fmts_conv;
273 			if (mu_isdigit(format[cur])) {
274 				int pos = get_num(format, cur, &n);
275 				if (format[pos] == '$') {
276 
277 #line 198
278  ((__bi_argcnt > (n-1+1)) ?   get_numeric_arg(env, (n-1+1) + 1, &num) :   ((
279 #line 198
280 	env_throw_bi(env, mfe_range, "sprintf", "Argument %u is not supplied",(unsigned) (n-1+1))
281 #line 198
282 ),(long ) 0));
283 					if (num > 0)
284 						prec = (unsigned) num;
285 					cur = pos + 1;
286 					break;
287 				}
288 			}
289 
290 #line 205
291  ((__bi_argcnt > (i+1)) ?   get_numeric_arg(env, (i+1) + 1, &num) :   ((
292 #line 205
293 	env_throw_bi(env, mfe_range, "sprintf", "Argument %u is not supplied",(unsigned) (i+1))
294 #line 205
295 ),(long ) 0));
296 			i++;
297 			if (num > 0)
298 				prec = (unsigned) num;
299 			break;
300 
301 		case fmts_conv:       /* Expect conversion specifier */
302 			if (!(flags & FMT_ALTPOS))
303 				argnum = i++;
304 			switch (format[cur]) {
305 			case 's':
306 
307 #line 216
308  ((__bi_argcnt > (argnum+1)) ?   get_string_arg(env, (argnum+1) + 1, &str) :   ((
309 #line 216
310 	env_throw_bi(env, mfe_range, "sprintf", "Argument %u is not supplied",(unsigned) (argnum+1))
311 #line 216
312 ),(char * MFL_DATASEG) 0));
313 				n = strlen(str);
314 				if (prec && prec < n)
315 					n = prec;
316 				if (width) {
317 					char *q, *s;
318 					if (n > width)
319 						width = n;
320 					q = s = mf_c_val(heap_tempspace(env, width + 1), ptr);
321 					q[width] = 0;
322 					memset(q, ' ', width);
323 					if (!(flags & FMT_ADJUST_LEFT)
324 					    && n < width) {
325 						s = q + width - n;
326 					}
327 					memcpy(s, str, n);
328 					str = q;
329 					n = width;
330 				}
331 				heap_obstack_grow(env, str, n);
332 				break;
333 
334 			case 'i':
335 			case 'd':
336 
337 #line 240
338  ((__bi_argcnt > (argnum+1)) ?   get_numeric_arg(env, (argnum+1) + 1, &num) :   ((
339 #line 240
340 	env_throw_bi(env, mfe_range, "sprintf", "Argument %u is not supplied",(unsigned) (argnum+1))
341 #line 240
342 ),(long ) 0));
343 				if (num < 0) {
344 					negative = 1;
345 					num = - num;
346 				} else
347 					negative = 0;
348 				/* If a precision is given with a
349 				   numeric conversion, the 0 flag is ignored.
350 				 */
351 				/* A - overrides a 0 if both are given. */
352 				if (prec || (flags & FMT_ADJUST_LEFT))
353 					flags &= ~FMT_PADZERO;
354 				snprintf(buf+1, sizeof(buf)-1, "%ld", num);
355 				str = buf + 1;
356 				n = strlen(str);
357 				if (prec && prec > n) {
358 					memmove(str + prec - n, str, n + 1);
359 					memset(str, '0', prec - n);
360 				}
361 
362 				if (flags & FMT_SIGNPFX) {
363 					buf[0] = negative ? '-' : '+';
364 					str = buf;
365 				} else if (flags & FMT_SPACEPFX) {
366 					buf[0] = negative ? '-' : ' ';
367 					str = buf;
368 				} else if (negative) {
369 					buf[0] = '-';
370 					str = buf;
371 				} else
372 					str = buf + 1;
373 				n = strlen(str);
374 
375 				if (width && width > n) {
376 					char *q;
377 					q = heap_obstack_grow(env, NULL, width);
378 					memset(q,
379 					       (flags & FMT_PADZERO) ?
380 					         '0' : ' ',
381 					       width);
382 					if (flags & FMT_ADJUST_LEFT)
383 						memcpy(q, str, n);
384 					else {
385 						if ((flags & FMT_PADZERO) &&
386 						    str == buf) {
387 							q[0] = *str++;
388 							n--;
389 						}
390 						memcpy(q + width - n, str, n);
391 					}
392 				} else
393 					heap_obstack_grow(env, str, n);
394 				break;
395 
396 			case 'u':
397 
398 #line 295
399  ((__bi_argcnt > (argnum+1)) ?   get_numeric_arg(env, (argnum+1) + 1, &num) :   ((
400 #line 295
401 	env_throw_bi(env, mfe_range, "sprintf", "Argument %u is not supplied",(unsigned) (argnum+1))
402 #line 295
403 ),(long ) 0));
404 				/* If a precision is given with a
405 				   numeric conversion, the 0 flag is ignored.
406 				*/
407 				/* A - overrides a 0 if both are given.*/
408 				if (prec || (flags & FMT_ADJUST_LEFT))
409 					flags &= ~FMT_PADZERO;
410 				snprintf(buf, sizeof(buf), "%lu", num);
411 				str = buf;
412 				n = strlen(str);
413 				if (prec && prec > n) {
414 					memmove(str + prec - n, str, n + 1);
415 					memset(str, '0', prec - n);
416 					n = prec;
417 				}
418 
419 				if (width && width > n) {
420 					char *q;
421 					q = heap_obstack_grow(env, NULL, width);
422 					memset(q,
423 					       (flags & FMT_PADZERO) ?
424 					         '0' : ' ',
425 					       width);
426 					if (flags & FMT_ADJUST_LEFT)
427 						memcpy(q, str, n);
428 					else
429 						memcpy(q + width - n, str, n);
430 				} else
431 					heap_obstack_grow(env, str, n);
432 				break;
433 
434 			case 'x':
435 			case 'X':
436 
437 #line 328
438  ((__bi_argcnt > (argnum+1)) ?   get_numeric_arg(env, (argnum+1) + 1, &num) :   ((
439 #line 328
440 	env_throw_bi(env, mfe_range, "sprintf", "Argument %u is not supplied",(unsigned) (argnum+1))
441 #line 328
442 ),(long ) 0));
443 				/* If a precision is given with a
444 				   numeric conversion, the 0 flag is ignored.
445 				*/
446 				/* A - overrides a 0 if both are given.*/
447 				if (prec || (flags & FMT_ADJUST_LEFT))
448 					flags &= ~FMT_PADZERO;
449 				fmtbuf[1] = format[cur];
450 				snprintf(buf+2, sizeof(buf)-2, fmtbuf, num);
451 				str = buf + 2;
452 				n = strlen(str);
453 				if (prec && prec > n) {
454 					memmove(str + prec - n, str, n + 1);
455 					memset(str, '0', prec - n);
456 					n = prec;
457 				}
458 
459 				if (flags & FMT_ALTERNATE) {
460 					*--str = format[cur];
461 					*--str = '0';
462 					n += 2;
463 				}
464 
465 				if (width && width > n) {
466 					char *q;
467 					q = heap_obstack_grow(env, NULL, width);
468 					memset(q,
469 					       (flags & FMT_PADZERO) ?
470 					         '0' : ' ',
471 					       width);
472 					if (flags & FMT_ADJUST_LEFT)
473 						memcpy(q, str, n);
474 					else {
475 						if (flags & FMT_ALTERNATE
476 						    && flags & FMT_PADZERO) {
477 							q[0] = *str++;
478 							q[1] = *str++;
479 							n -= 2;
480 						}
481 						memcpy(q + width - n, str, n);
482 					}
483 				} else
484 					heap_obstack_grow(env, str, n);
485 				break;
486 
487 			case 'o':
488 
489 #line 374
490  ((__bi_argcnt > (argnum+1)) ?   get_numeric_arg(env, (argnum+1) + 1, &num) :   ((
491 #line 374
492 	env_throw_bi(env, mfe_range, "sprintf", "Argument %u is not supplied",(unsigned) (argnum+1))
493 #line 374
494 ),(long ) 0));
495 				/* If a precision is given with a
496 				   numeric conversion, the 0 flag is ignored.
497 				*/
498 				/* A - overrides a 0 if both are given.*/
499 				if (prec || (flags & FMT_ADJUST_LEFT))
500 					flags &= ~FMT_PADZERO;
501 				snprintf(buf+1, sizeof(buf)-1, "%lo", num);
502 				str = buf + 2;
503 				n = strlen(str);
504 				if (prec && prec > n) {
505 					memmove(str + prec - n, str, n + 1);
506 					memset(str, '0', prec - n);
507 				}
508 
509 				if ((flags & FMT_ALTERNATE) && *str != '0') {
510 					*--str = '0';
511 					n++;
512 				}
513 
514 				if (width && width > n) {
515 					char *q;
516 					q = heap_obstack_grow(env, NULL, width);
517 					memset(q,
518 					       (flags & FMT_PADZERO) ?
519 					         '0' : ' ',
520 					       width);
521 					if (flags & FMT_ADJUST_LEFT)
522 						memcpy(q, str, n);
523 					else
524 						memcpy(q + width - n, str, n);
525 				} else
526 					heap_obstack_grow(env, str, n);
527 				break;
528 
529 			default:
530 				heap_obstack_grow(env, &format[start], cur - start + 1);
531 #line 412
532 			}
533 
534 			cur++;
535 			state = fmts_copy;
536 		}
537 	}
538 	do { char __c = 0; heap_obstack_grow(env, &__c, 1); } while(0);
539 	adjust_stack(env, __bi_argcnt + 1);
540 
541 #line 420
542 do {
543 #line 420
544   push(env, (STKVAL) (heap_obstack_finish(env)));
545 #line 420
546   goto endlab;
547 #line 420
548 } while (0);
549 }
550 endlab:
551 #line 422
552         env_function_cleanup_flush(env, NULL);
553 #line 422
554 	return;
555 #line 422
556 }
557 
558 #line 982 "../../src/builtin/snarf.m4"
559 
560 #line 982
561 
562 #line 982
563 
564 #line 982
565 void
566 #line 982
sprintf_init_builtin(void)567 sprintf_init_builtin(void)
568 #line 982
569 {
570 #line 982
571 
572 #line 982
573 	#line 51 "sprintf.bi"
574 va_builtin_install_ex("sprintf", bi_sprintf, 0, dtype_string, 1, 0, 0|MFD_BUILTIN_VARIADIC|MFD_BUILTIN_NO_PROMOTE, dtype_string);
575 
576 #line 982 "../../src/builtin/snarf.m4"
577 
578 #line 982
579 }
580 #line 982 "../../src/builtin/snarf.m4"
581 
582