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.
4 Copyright (C) 1995 Free Software Foundation, Inc.
5 Rewritten by mly to use varargs.h.
6 Rewritten from scratch by Ben Wing (February 1995) for Mule; expanded
9 This file is part of XEmacs.
11 XEmacs is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2, or (at your option) any
16 XEmacs is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with XEmacs; see the file COPYING. If not, write to
23 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24 Boston, MA 02111-1307, USA. */
26 /* Synched up with: Rewritten. Not in FSF. */
34 static CONST char *valid_flags = "-+ #0";
36 static CONST char *valid_converters = "diouxXfeEgGcsS";
37 static CONST char *int_converters = "dic";
38 static CONST char *unsigned_int_converters = "ouxX";
39 static CONST char *double_converters = "feEgG";
40 static CONST char *string_converters = "sS";
42 typedef struct printf_spec printf_spec;
45 int argnum; /* which argument does this spec want? This is one-based:
46 The first argument given is numbered 1, the second
47 is 2, etc. This is to handle %##$x-type specs. */
50 unsigned int minus_flag:1;
51 unsigned int plus_flag:1;
52 unsigned int space_flag:1;
53 unsigned int number_flag:1;
54 unsigned int zero_flag:1;
55 unsigned int h_flag:1;
56 unsigned int l_flag:1;
57 unsigned int forwarding_precision:1;
58 char converter; /* converter character or 0 for dummy marker
59 indicating literal text at the end of the
61 Bytecount text_before; /* position of the first character of the
62 block of literal text before this spec */
63 Bytecount text_before_len; /* length of that text */
66 typedef union printf_arg printf_arg;
77 /* We maintain a list of all the % specs in the specification,
78 along with the offset and length of the block of literal text
79 before each spec. In addition, we have a "dummy" spec that
80 represents all the literal text at the end of the specification.
81 Its converter is 0. */
85 Dynarr_declare (struct printf_spec);
90 Dynarr_declare (union printf_arg);
93 /* Append STRING (of length LEN) to STREAM. MINLEN is the minimum field
94 width. If MINUS_FLAG is set, left-justify the string in its field;
95 otherwise, right-justify. If ZERO_FLAG is set, pad with 0's; otherwise
96 pad with spaces. If MAXLEN is non-negative, the string is first
97 truncated to that many character.
99 Note that MINLEN and MAXLEN are Charcounts but LEN is a Bytecount. */
102 doprnt_1 (Lisp_Object stream, CONST Bufbyte *string, Bytecount len,
103 Charcount minlen, Charcount maxlen, int minus_flag, int zero_flag)
107 Lstream *lstr = XLSTREAM (stream);
109 cclen = bytecount_to_charcount (string, len);
116 /* Padding at beginning to right-justify ... */
117 if (minlen > cclen && !minus_flag)
119 int to_add = minlen - cclen;
122 Lstream_putc (lstr, pad);
128 len = charcount_to_bytecount (string, min (maxlen, cclen));
129 Lstream_write (lstr, string, len);
131 /* Padding at end to left-justify ... */
132 if (minlen > cclen && minus_flag)
134 int to_add = minlen - cclen;
137 Lstream_putc (lstr, pad);
143 static CONST Bufbyte *
144 parse_off_posnum (CONST Bufbyte *start, CONST Bufbyte *end, int *returned_num)
146 Bufbyte arg_convert[100];
147 REGISTER Bufbyte *arg_ptr = arg_convert;
150 while (start != end && isdigit (*start))
152 if ((size_t) (arg_ptr - arg_convert) >= sizeof (arg_convert) - 1)
153 error ("Format converter number too large");
154 *arg_ptr++ = *start++;
157 if (arg_convert != arg_ptr)
158 *returned_num = atoi ((char *) arg_convert);
162 #define NEXT_ASCII_BYTE(ch) \
164 if (fmt == fmt_end) \
165 error ("Premature end of format string"); \
168 error ("Non-ASCII character in format converter spec"); \
172 #define RESOLVE_FLAG_CONFLICTS(spec) \
174 if (spec.space_flag && spec.plus_flag) \
175 spec.space_flag = 0; \
176 if (spec.zero_flag && spec.space_flag) \
177 spec.zero_flag = 0; \
180 static printf_spec_dynarr *
181 parse_doprnt_spec (CONST Bufbyte *format, Bytecount format_length)
183 CONST Bufbyte *fmt = format;
184 CONST Bufbyte *fmt_end = format + format_length;
185 printf_spec_dynarr *specs = Dynarr_new (printf_spec);
190 struct printf_spec spec;
191 CONST Bufbyte *text_end;
197 text_end = (Bufbyte *) memchr (fmt, '%', fmt_end - fmt);
200 spec.text_before = fmt - format;
201 spec.text_before_len = text_end - fmt;
205 fmt++; /* skip over % */
207 /* A % is special -- no arg number. According to ANSI specs,
208 field width does not apply to %% conversion. */
209 if (fmt != fmt_end && *fmt == '%')
211 spec.converter = '%';
212 Dynarr_add (specs, spec);
217 /* Is there a field number specifier? */
222 ptr = parse_off_posnum (fmt, fmt_end, &fieldspec);
223 if (fieldspec > 0 && ptr != fmt_end && *ptr == '$')
225 /* There is a format specifier */
226 prev_argnum = fieldspec;
231 spec.argnum = prev_argnum;
234 /* Parse off any flags */
235 NEXT_ASCII_BYTE (ch);
236 while (strchr (valid_flags, ch))
240 case '-': spec.minus_flag = 1; break;
241 case '+': spec.plus_flag = 1; break;
242 case ' ': spec.space_flag = 1; break;
243 case '#': spec.number_flag = 1; break;
244 case '0': spec.zero_flag = 1; break;
247 NEXT_ASCII_BYTE (ch);
250 /* Parse off the minimum field width */
254 * * means the field width was passed as an argument.
255 * Mark the current spec as one that forwards its
256 * field width and flags to the next spec in the array.
257 * Then create a new spec and continue with the parsing.
259 if (fmt != fmt_end && *fmt == '*')
261 spec.converter = '*';
262 RESOLVE_FLAG_CONFLICTS(spec);
263 Dynarr_add (specs, spec);
265 spec.argnum = ++prev_argnum;
270 fmt = parse_off_posnum (fmt, fmt_end, &spec.minwidth);
271 if (spec.minwidth == -1)
275 /* Parse off any precision specified */
276 NEXT_ASCII_BYTE (ch);
280 * * means the precision was passed as an argument.
281 * Mark the current spec as one that forwards its
282 * fieldwidth, flags and precision to the next spec in
283 * the array. Then create a new spec and continue
286 if (fmt != fmt_end && *fmt == '*')
288 spec.converter = '*';
289 spec.forwarding_precision = 1;
290 RESOLVE_FLAG_CONFLICTS(spec);
291 Dynarr_add (specs, spec);
293 spec.argnum = ++prev_argnum;
298 fmt = parse_off_posnum (fmt, fmt_end, &spec.precision);
299 if (spec.precision == -1)
302 NEXT_ASCII_BYTE (ch);
305 /* No precision specified */
308 /* Parse off h or l flag */
309 if (ch == 'h' || ch == 'l')
315 NEXT_ASCII_BYTE (ch);
318 if (!strchr (valid_converters, ch))
319 error ("Invalid converter character %c", ch);
323 RESOLVE_FLAG_CONFLICTS(spec);
324 Dynarr_add (specs, spec);
327 RETURN_NOT_REACHED(specs) /* suppress compiler warning */
331 get_args_needed (printf_spec_dynarr *specs)
336 /* Figure out how many args are needed. This may be less than
337 the number of specs because a spec could be %% or could be
338 missing (literal text at end of format string) or there
339 could be specs where the field number is explicitly given.
340 We just look for the maximum argument number that's referenced. */
342 for (i = 0; i < Dynarr_length (specs); i++)
344 char ch = Dynarr_at (specs, i).converter;
347 int argnum = Dynarr_at (specs, i).argnum;
348 if (argnum > args_needed)
349 args_needed = argnum;
356 static printf_arg_dynarr *
357 get_doprnt_args (printf_spec_dynarr *specs, va_list vargs)
359 printf_arg_dynarr *args = Dynarr_new (printf_arg);
360 union printf_arg arg;
362 int args_needed = get_args_needed (specs);
365 for (i = 1; i <= args_needed; i++)
369 struct printf_spec *spec = 0;
371 for (j = 0; j < Dynarr_length (specs); j++)
373 spec = Dynarr_atp (specs, j);
374 if (spec->argnum == i)
378 if (j == Dynarr_length (specs))
379 error ("No conversion spec for argument %d", i);
381 ch = spec->converter;
383 /* int even if ch == 'c': "the type used in va_arg is supposed to
384 match the actual type **after default promotions**." */
386 if (strchr (int_converters, ch))
389 arg.i = va_arg (vargs, int /* short */);
390 else if (spec->l_flag)
391 arg.l = va_arg (vargs, long);
393 arg.i = va_arg (vargs, int);
395 else if (strchr (unsigned_int_converters, ch))
398 arg.ui = va_arg (vargs, unsigned int /* unsigned short */);
399 else if (spec->l_flag)
400 arg.ul = va_arg (vargs, unsigned long);
402 arg.ui = va_arg (vargs, unsigned int);
404 else if (strchr (double_converters, ch))
405 arg.d = va_arg (vargs, double);
406 else if (strchr (string_converters, ch))
407 arg.bp = va_arg (vargs, Bufbyte *);
410 Dynarr_add (args, arg);
416 /* Generate output from a format-spec FORMAT, of length FORMAT_LENGTH.
417 Output goes in BUFFER, which has room for BUFSIZE bytes.
418 If the output does not fit, truncate it to fit.
419 Returns the number of bytes stored into BUFFER.
420 LARGS or VARGS points to the arguments, and NARGS says how many.
421 if LARGS is non-zero, it should be a pointer to NARGS worth of
422 Lisp arguments. Otherwise, VARGS should be a va_list referring
426 emacs_doprnt_1 (Lisp_Object stream, CONST Bufbyte *format_nonreloc,
427 Lisp_Object format_reloc, Bytecount format_length,
429 /* #### Gag me, gag me, gag me */
430 CONST Lisp_Object *largs, va_list vargs)
432 printf_spec_dynarr *specs = 0;
433 printf_arg_dynarr *args = 0;
435 int init_byte_count = Lstream_byte_count (XLSTREAM (stream));
437 if (!NILP (format_reloc))
439 format_nonreloc = XSTRING_DATA (format_reloc);
440 format_length = XSTRING_LENGTH (format_reloc);
442 if (format_length < 0)
443 format_length = (Bytecount) strlen ((CONST char *) format_nonreloc);
445 specs = parse_doprnt_spec (format_nonreloc, format_length);
448 /* allow too many args for string, but not too few */
449 if (nargs < get_args_needed (specs))
450 signal_error (Qwrong_number_of_arguments,
453 !NILP (format_reloc) ? format_reloc :
454 make_string (format_nonreloc, format_length)));
458 args = get_doprnt_args (specs, vargs);
461 for (i = 0; i < Dynarr_length (specs); i++)
463 struct printf_spec *spec = Dynarr_atp (specs, i);
466 /* Copy the text before */
467 if (!NILP (format_reloc)) /* refetch in case of GC below */
468 format_nonreloc = XSTRING_DATA (format_reloc);
469 doprnt_1 (stream, format_nonreloc + spec->text_before,
470 spec->text_before_len, 0, -1, 0, 0);
472 ch = spec->converter;
479 doprnt_1 (stream, (Bufbyte *) &ch, 1, 0, -1, 0, 0);
483 /* The char '*' as converter means the field width, precision
484 was specified as an argument. Extract the data and forward
485 it to the next spec, to which it will apply. */
488 struct printf_spec *nextspec = Dynarr_atp (specs, i + 1);
489 Lisp_Object obj = largs[spec->argnum - 1];
493 if (spec->forwarding_precision)
495 nextspec->precision = XINT (obj);
496 nextspec->minwidth = spec->minwidth;
500 nextspec->minwidth = XINT (obj);
503 spec->minus_flag = 1;
504 nextspec->minwidth = - nextspec->minwidth;
507 nextspec->minus_flag = spec->minus_flag;
508 nextspec->plus_flag = spec->plus_flag;
509 nextspec->space_flag = spec->space_flag;
510 nextspec->number_flag = spec->number_flag;
511 nextspec->zero_flag = spec->zero_flag;
516 if (largs && (spec->argnum < 1 || spec->argnum > nargs))
517 error ("Invalid repositioning argument %d", spec->argnum);
519 else if (ch == 'S' || ch == 's')
522 Bytecount string_len;
526 string = Dynarr_at (args, spec->argnum - 1).bp;
527 /* error() can be called with null string arguments.
528 E.g., in fileio.c, the return value of strerror()
529 is never checked. We'll print (null), like some
530 printf implementations do. Would it be better (and safe)
531 to signal an error instead? Or should we just use the
532 empty string? -dkindred@cs.cmu.edu 8/1997
535 string = (Bufbyte *) "(null)";
536 string_len = strlen ((char *) string);
540 Lisp_Object obj = largs[spec->argnum - 1];
541 struct Lisp_String *ls;
545 /* For `S', prin1 the argument and then treat like
547 ls = XSTRING (Fprin1_to_string (obj, Qnil));
549 else if (STRINGP (obj))
551 else if (SYMBOLP (obj))
552 ls = XSYMBOL (obj)->name;
555 /* convert to string using princ. */
556 ls = XSTRING (Fprin1_to_string (obj, Qt));
558 string = string_data (ls);
559 string_len = string_length (ls);
562 doprnt_1 (stream, string, string_len, spec->minwidth,
563 spec->precision, spec->minus_flag, spec->zero_flag);
568 /* Must be a number. */
569 union printf_arg arg;
573 arg = Dynarr_at (args, spec->argnum - 1);
577 Lisp_Object obj = largs[spec->argnum - 1];
579 obj = make_int (XCHAR (obj));
580 if (!INT_OR_FLOATP (obj))
582 error ("format specifier %%%c doesn't match argument type",
585 else if (strchr (double_converters, ch))
586 arg.d = XFLOATINT (obj);
592 val = XINT (Ftruncate (obj));
595 if (strchr (unsigned_int_converters, ch))
598 arg.ul = (unsigned long) val;
600 arg.ui = (unsigned int) val;
617 Bufbyte charbuf[MAX_EMCHAR_LEN];
624 if (!valid_char_p (a))
625 error ("invalid character value %d to %%c spec", a);
627 charlen = set_charptr_emchar (charbuf, a);
628 doprnt_1 (stream, charbuf, charlen, spec->minwidth,
629 -1, spec->minus_flag, spec->zero_flag);
634 char text_to_print[500];
635 char constructed_spec[100];
637 /* Partially reconstruct the spec and use sprintf() to
638 format the string. */
640 /* Make sure nothing stupid happens */
641 /* DO NOT REMOVE THE (int) CAST! Incorrect results will
643 spec->precision = min (spec->precision,
644 (int) (sizeof (text_to_print) - 50));
646 constructed_spec[0] = 0;
647 strcat (constructed_spec, "%");
649 strcat (constructed_spec, "+");
650 if (spec->space_flag)
651 strcat (constructed_spec, " ");
652 if (spec->number_flag)
653 strcat (constructed_spec, "#");
654 if (spec->precision >= 0)
656 strcat (constructed_spec, ".");
657 long_to_string (constructed_spec + strlen (constructed_spec),
660 sprintf (constructed_spec + strlen (constructed_spec), "%c", ch);
662 /* sprintf the mofo */
663 /* we have to use separate calls to sprintf(), rather than
664 a single big conditional, because of the different types
666 if (strchr (double_converters, ch))
667 sprintf (text_to_print, constructed_spec, arg.d);
668 else if (strchr (unsigned_int_converters, ch))
671 sprintf (text_to_print, constructed_spec, arg.ul);
673 sprintf (text_to_print, constructed_spec, arg.ui);
678 sprintf (text_to_print, constructed_spec, arg.l);
680 sprintf (text_to_print, constructed_spec, arg.i);
683 doprnt_1 (stream, (Bufbyte *) text_to_print,
684 strlen (text_to_print),
685 spec->minwidth, -1, spec->minus_flag, spec->zero_flag);
690 /* #### will not get freed if error */
695 return Lstream_byte_count (XLSTREAM (stream)) - init_byte_count;
698 /* You really don't want to know why this is necessary... */
700 emacs_doprnt_2 (Lisp_Object stream, CONST Bufbyte *format_nonreloc,
701 Lisp_Object format_reloc, Bytecount format_length, int nargs,
702 CONST Lisp_Object *largs, ...)
706 va_start (vargs, largs);
707 val = emacs_doprnt_1 (stream, format_nonreloc, format_reloc,
708 format_length, nargs, largs, vargs);
713 /*********************** external entry points ***********************/
716 /* A note about I18N3 translating: the format string should get
717 translated, but not under all circumstances. When the format
718 string is a Lisp string, what should happen is that Fformat()
719 should format the untranslated args[0] and return that, and also
720 call Fgettext() on args[0] and, if that is different, format it
721 and store it in the `string-translatable' property of
722 the returned string. See Fgettext(). */
725 /* Send formatted output to STREAM. The format string comes from
726 either FORMAT_NONRELOC (of length FORMAT_LENGTH; -1 means use
727 strlen() to determine the length) or from FORMAT_RELOC, which
728 should be a Lisp string. Return the number of bytes written
731 DO NOT pass the data from a Lisp string as the FORMAT_NONRELOC
732 parameter, because this function can cause GC. */
735 emacs_doprnt_c (Lisp_Object stream, CONST Bufbyte *format_nonreloc,
736 Lisp_Object format_reloc, Bytecount format_length,
742 va_start (vargs, format_length);
743 val = emacs_doprnt_1 (stream, format_nonreloc, format_reloc,
744 format_length, 0, 0, vargs);
749 /* Like emacs_doprnt_c but the args come in va_list format. */
752 emacs_doprnt_va (Lisp_Object stream, CONST Bufbyte *format_nonreloc,
753 Lisp_Object format_reloc, Bytecount format_length,
756 return emacs_doprnt_1 (stream, format_nonreloc, format_reloc,
757 format_length, 0, 0, vargs);
760 /* Like emacs_doprnt_c but the args are Lisp objects instead of
761 C arguments. This causes somewhat different behavior from
762 the above two functions (which should act like printf).
763 See `format' for a description of this behavior. */
766 emacs_doprnt_lisp (Lisp_Object stream, CONST Bufbyte *format_nonreloc,
767 Lisp_Object format_reloc, Bytecount format_length,
768 int nargs, CONST Lisp_Object *largs)
770 return emacs_doprnt_2 (stream, format_nonreloc, format_reloc,
771 format_length, nargs, largs);
774 /* Like the previous function but takes a variable number of arguments. */
777 emacs_doprnt_lisp_2 (Lisp_Object stream, CONST Bufbyte *format_nonreloc,
778 Lisp_Object format_reloc, Bytecount format_length,
783 Lisp_Object *foo = alloca_array (Lisp_Object, nargs);
785 va_start (vargs, nargs);
786 for (i = 0; i < nargs; i++)
787 foo[i] = va_arg (vargs, Lisp_Object);
790 return emacs_doprnt_2 (stream, format_nonreloc, format_reloc,
791 format_length, nargs, foo);
794 /* The following four functions work like the above three but
795 return their output as a Lisp string instead of sending it
799 emacs_doprnt_string_c (CONST Bufbyte *format_nonreloc,
800 Lisp_Object format_reloc, Bytecount format_length,
805 Lisp_Object stream = make_resizing_buffer_output_stream ();
809 va_start (vargs, format_length);
810 emacs_doprnt_1 (stream, format_nonreloc, format_reloc,
811 format_length, 0, 0, vargs);
813 Lstream_flush (XLSTREAM (stream));
814 obj = make_string (resizing_buffer_stream_ptr (XLSTREAM (stream)),
815 Lstream_byte_count (XLSTREAM (stream)));
817 Lstream_delete (XLSTREAM (stream));
822 emacs_doprnt_string_va (CONST Bufbyte *format_nonreloc,
823 Lisp_Object format_reloc, Bytecount format_length,
826 /* I'm fairly sure that this function cannot actually GC.
827 That can only happen when the arguments to emacs_doprnt_1() are
828 Lisp objects rather than C args. */
830 Lisp_Object stream = make_resizing_buffer_output_stream ();
834 emacs_doprnt_1 (stream, format_nonreloc, format_reloc,
835 format_length, 0, 0, vargs);
836 Lstream_flush (XLSTREAM (stream));
837 obj = make_string (resizing_buffer_stream_ptr (XLSTREAM (stream)),
838 Lstream_byte_count (XLSTREAM (stream)));
840 Lstream_delete (XLSTREAM (stream));
845 emacs_doprnt_string_lisp (CONST Bufbyte *format_nonreloc,
846 Lisp_Object format_reloc, Bytecount format_length,
847 int nargs, CONST Lisp_Object *largs)
850 Lisp_Object stream = make_resizing_buffer_output_stream ();
854 emacs_doprnt_2 (stream, format_nonreloc, format_reloc,
855 format_length, nargs, largs);
856 Lstream_flush (XLSTREAM (stream));
857 obj = make_string (resizing_buffer_stream_ptr (XLSTREAM (stream)),
858 Lstream_byte_count (XLSTREAM (stream)));
860 Lstream_delete (XLSTREAM (stream));
865 emacs_doprnt_string_lisp_2 (CONST Bufbyte *format_nonreloc,
866 Lisp_Object format_reloc, Bytecount format_length,
870 Lisp_Object stream = make_resizing_buffer_output_stream ();
874 Lisp_Object *foo = alloca_array (Lisp_Object, nargs);
876 va_start (vargs, nargs);
877 for (i = 0; i < nargs; i++)
878 foo[i] = va_arg (vargs, Lisp_Object);
882 emacs_doprnt_2 (stream, format_nonreloc, format_reloc,
883 format_length, nargs, foo);
884 Lstream_flush (XLSTREAM (stream));
885 obj = make_string (resizing_buffer_stream_ptr (XLSTREAM (stream)),
886 Lstream_byte_count (XLSTREAM (stream)));
888 Lstream_delete (XLSTREAM (stream));