Mercurial > hg > xemacs-beta
comparison src/doprnt.c @ 412:697ef44129c6 r21-2-14
Import from CVS: tag r21-2-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:20:41 +0200 |
parents | de805c49cfc1 |
children | 11054d720c21 |
comparison
equal
deleted
inserted
replaced
411:12e008d41344 | 412:697ef44129c6 |
---|---|
29 #include "lisp.h" | 29 #include "lisp.h" |
30 | 30 |
31 #include "buffer.h" | 31 #include "buffer.h" |
32 #include "lstream.h" | 32 #include "lstream.h" |
33 | 33 |
34 static const char *valid_flags = "-+ #0"; | 34 static CONST char *valid_flags = "-+ #0"; |
35 | 35 |
36 static const char *valid_converters = "diouxXfeEgGcsS"; | 36 static CONST char *valid_converters = "diouxXfeEgGcsS"; |
37 static const char *int_converters = "dic"; | 37 static CONST char *int_converters = "dic"; |
38 static const char *unsigned_int_converters = "ouxX"; | 38 static CONST char *unsigned_int_converters = "ouxX"; |
39 static const char *double_converters = "feEgG"; | 39 static CONST char *double_converters = "feEgG"; |
40 static const char *string_converters = "sS"; | 40 static CONST char *string_converters = "sS"; |
41 | 41 |
42 typedef struct printf_spec printf_spec; | 42 typedef struct printf_spec printf_spec; |
43 struct printf_spec | 43 struct printf_spec |
44 { | 44 { |
45 int argnum; /* which argument does this spec want? This is one-based: | 45 int argnum; /* which argument does this spec want? This is one-based: |
97 truncated to that many character. | 97 truncated to that many character. |
98 | 98 |
99 Note that MINLEN and MAXLEN are Charcounts but LEN is a Bytecount. */ | 99 Note that MINLEN and MAXLEN are Charcounts but LEN is a Bytecount. */ |
100 | 100 |
101 static void | 101 static void |
102 doprnt_1 (Lisp_Object stream, const Bufbyte *string, Bytecount len, | 102 doprnt_1 (Lisp_Object stream, CONST Bufbyte *string, Bytecount len, |
103 Charcount minlen, Charcount maxlen, int minus_flag, int zero_flag) | 103 Charcount minlen, Charcount maxlen, int minus_flag, int zero_flag) |
104 { | 104 { |
105 Charcount cclen; | 105 Charcount cclen; |
106 Bufbyte pad; | 106 Bufbyte pad; |
107 Lstream *lstr = XLSTREAM (stream); | 107 Lstream *lstr = XLSTREAM (stream); |
138 to_add--; | 138 to_add--; |
139 } | 139 } |
140 } | 140 } |
141 } | 141 } |
142 | 142 |
143 static const Bufbyte * | 143 static CONST Bufbyte * |
144 parse_off_posnum (const Bufbyte *start, const Bufbyte *end, int *returned_num) | 144 parse_off_posnum (CONST Bufbyte *start, CONST Bufbyte *end, int *returned_num) |
145 { | 145 { |
146 Bufbyte arg_convert[100]; | 146 Bufbyte arg_convert[100]; |
147 REGISTER Bufbyte *arg_ptr = arg_convert; | 147 REGISTER Bufbyte *arg_ptr = arg_convert; |
148 | 148 |
149 *returned_num = -1; | 149 *returned_num = -1; |
176 if (spec.zero_flag && spec.space_flag) \ | 176 if (spec.zero_flag && spec.space_flag) \ |
177 spec.zero_flag = 0; \ | 177 spec.zero_flag = 0; \ |
178 } while (0) | 178 } while (0) |
179 | 179 |
180 static printf_spec_dynarr * | 180 static printf_spec_dynarr * |
181 parse_doprnt_spec (const Bufbyte *format, Bytecount format_length) | 181 parse_doprnt_spec (CONST Bufbyte *format, Bytecount format_length) |
182 { | 182 { |
183 const Bufbyte *fmt = format; | 183 CONST Bufbyte *fmt = format; |
184 const Bufbyte *fmt_end = format + format_length; | 184 CONST Bufbyte *fmt_end = format + format_length; |
185 printf_spec_dynarr *specs = Dynarr_new (printf_spec); | 185 printf_spec_dynarr *specs = Dynarr_new (printf_spec); |
186 int prev_argnum = 0; | 186 int prev_argnum = 0; |
187 | 187 |
188 while (1) | 188 while (1) |
189 { | 189 { |
190 struct printf_spec spec; | 190 struct printf_spec spec; |
191 const Bufbyte *text_end; | 191 CONST Bufbyte *text_end; |
192 Bufbyte ch; | 192 Bufbyte ch; |
193 | 193 |
194 xzero (spec); | 194 xzero (spec); |
195 if (fmt == fmt_end) | 195 if (fmt == fmt_end) |
196 return specs; | 196 return specs; |
214 continue; | 214 continue; |
215 } | 215 } |
216 | 216 |
217 /* Is there a field number specifier? */ | 217 /* Is there a field number specifier? */ |
218 { | 218 { |
219 const Bufbyte *ptr; | 219 CONST Bufbyte *ptr; |
220 int fieldspec; | 220 int fieldspec; |
221 | 221 |
222 ptr = parse_off_posnum (fmt, fmt_end, &fieldspec); | 222 ptr = parse_off_posnum (fmt, fmt_end, &fieldspec); |
223 if (fieldspec > 0 && ptr != fmt_end && *ptr == '$') | 223 if (fieldspec > 0 && ptr != fmt_end && *ptr == '$') |
224 { | 224 { |
384 match the actual type **after default promotions**." */ | 384 match the actual type **after default promotions**." */ |
385 | 385 |
386 if (strchr (int_converters, ch)) | 386 if (strchr (int_converters, ch)) |
387 { | 387 { |
388 if (spec->h_flag) | 388 if (spec->h_flag) |
389 arg.i = va_arg (vargs, int /* short */); | 389 arg.i = va_arg (vargs, short); |
390 else if (spec->l_flag) | 390 else if (spec->l_flag) |
391 arg.l = va_arg (vargs, long); | 391 arg.l = va_arg (vargs, long); |
392 else | 392 else |
393 arg.i = va_arg (vargs, int); | 393 arg.i = va_arg (vargs, int); |
394 } | 394 } |
395 else if (strchr (unsigned_int_converters, ch)) | 395 else if (strchr (unsigned_int_converters, ch)) |
396 { | 396 { |
397 if (spec->h_flag) | 397 if (spec->h_flag) |
398 arg.ui = va_arg (vargs, unsigned int /* unsigned short */); | 398 arg.ui = va_arg (vargs, unsigned short); |
399 else if (spec->l_flag) | 399 else if (spec->l_flag) |
400 arg.ul = va_arg (vargs, unsigned long); | 400 arg.ul = va_arg (vargs, unsigned long); |
401 else | 401 else |
402 arg.ui = va_arg (vargs, unsigned int); | 402 arg.ui = va_arg (vargs, unsigned int); |
403 } | 403 } |
421 if LARGS is non-zero, it should be a pointer to NARGS worth of | 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 | 422 Lisp arguments. Otherwise, VARGS should be a va_list referring |
423 to the arguments. */ | 423 to the arguments. */ |
424 | 424 |
425 static Bytecount | 425 static Bytecount |
426 emacs_doprnt_1 (Lisp_Object stream, const Bufbyte *format_nonreloc, | 426 emacs_doprnt_1 (Lisp_Object stream, CONST Bufbyte *format_nonreloc, |
427 Lisp_Object format_reloc, Bytecount format_length, | 427 Lisp_Object format_reloc, Bytecount format_length, |
428 int nargs, | 428 int nargs, |
429 /* #### Gag me, gag me, gag me */ | 429 /* #### Gag me, gag me, gag me */ |
430 const Lisp_Object *largs, va_list vargs) | 430 CONST Lisp_Object *largs, va_list vargs) |
431 { | 431 { |
432 printf_spec_dynarr *specs = 0; | 432 printf_spec_dynarr *specs = 0; |
433 printf_arg_dynarr *args = 0; | 433 printf_arg_dynarr *args = 0; |
434 REGISTER int i; | 434 REGISTER int i; |
435 int init_byte_count = Lstream_byte_count (XLSTREAM (stream)); | 435 int init_byte_count = Lstream_byte_count (XLSTREAM (stream)); |
438 { | 438 { |
439 format_nonreloc = XSTRING_DATA (format_reloc); | 439 format_nonreloc = XSTRING_DATA (format_reloc); |
440 format_length = XSTRING_LENGTH (format_reloc); | 440 format_length = XSTRING_LENGTH (format_reloc); |
441 } | 441 } |
442 if (format_length < 0) | 442 if (format_length < 0) |
443 format_length = (Bytecount) strlen ((const char *) format_nonreloc); | 443 format_length = (Bytecount) strlen ((CONST char *) format_nonreloc); |
444 | 444 |
445 specs = parse_doprnt_spec (format_nonreloc, format_length); | 445 specs = parse_doprnt_spec (format_nonreloc, format_length); |
446 if (largs) | 446 if (largs) |
447 { | 447 { |
448 /* allow too many args for string, but not too few */ | 448 /* allow too many args for string, but not too few */ |
536 string_len = strlen ((char *) string); | 536 string_len = strlen ((char *) string); |
537 } | 537 } |
538 else | 538 else |
539 { | 539 { |
540 Lisp_Object obj = largs[spec->argnum - 1]; | 540 Lisp_Object obj = largs[spec->argnum - 1]; |
541 Lisp_String *ls; | 541 struct Lisp_String *ls; |
542 | 542 |
543 if (ch == 'S') | 543 if (ch == 'S') |
544 { | 544 { |
545 /* For `S', prin1 the argument and then treat like | 545 /* For `S', prin1 the argument and then treat like |
546 a string. */ | 546 a string. */ |
655 { | 655 { |
656 strcat (constructed_spec, "."); | 656 strcat (constructed_spec, "."); |
657 long_to_string (constructed_spec + strlen (constructed_spec), | 657 long_to_string (constructed_spec + strlen (constructed_spec), |
658 spec->precision); | 658 spec->precision); |
659 } | 659 } |
660 sprintf (constructed_spec + strlen (constructed_spec), "%c", ch); | |
660 | 661 |
661 /* sprintf the mofo */ | 662 /* sprintf the mofo */ |
662 /* we have to use separate calls to sprintf(), rather than | 663 /* we have to use separate calls to sprintf(), rather than |
663 a single big conditional, because of the different types | 664 a single big conditional, because of the different types |
664 of the arguments */ | 665 of the arguments */ |
665 if (strchr (double_converters, ch)) | 666 if (strchr (double_converters, ch)) |
666 { | 667 sprintf (text_to_print, constructed_spec, arg.d); |
667 sprintf (constructed_spec + strlen (constructed_spec), | |
668 "%c", ch); | |
669 sprintf (text_to_print, constructed_spec, arg.d); | |
670 } | |
671 else if (strchr (unsigned_int_converters, ch)) | 668 else if (strchr (unsigned_int_converters, ch)) |
672 { | 669 { |
673 sprintf (constructed_spec + strlen (constructed_spec), | |
674 "%c", ch); | |
675 if (spec->l_flag) | 670 if (spec->l_flag) |
676 sprintf (text_to_print, constructed_spec, arg.ul); | 671 sprintf (text_to_print, constructed_spec, arg.ul); |
677 else | 672 else |
678 sprintf (text_to_print, constructed_spec, arg.ui); | 673 sprintf (text_to_print, constructed_spec, arg.ui); |
679 } | 674 } |
680 else | 675 else |
681 { | 676 { |
682 if (spec->zero_flag && spec->minwidth) | |
683 sprintf (constructed_spec + strlen (constructed_spec), | |
684 "0%d%c", spec->minwidth, ch); | |
685 else | |
686 sprintf (constructed_spec + strlen (constructed_spec), | |
687 "%c", ch); | |
688 if (spec->l_flag) | 677 if (spec->l_flag) |
689 sprintf (text_to_print, constructed_spec, arg.l); | 678 sprintf (text_to_print, constructed_spec, arg.l); |
690 else | 679 else |
691 sprintf (text_to_print, constructed_spec, arg.i); | 680 sprintf (text_to_print, constructed_spec, arg.i); |
692 } | 681 } |
706 return Lstream_byte_count (XLSTREAM (stream)) - init_byte_count; | 695 return Lstream_byte_count (XLSTREAM (stream)) - init_byte_count; |
707 } | 696 } |
708 | 697 |
709 /* You really don't want to know why this is necessary... */ | 698 /* You really don't want to know why this is necessary... */ |
710 static Bytecount | 699 static Bytecount |
711 emacs_doprnt_2 (Lisp_Object stream, const Bufbyte *format_nonreloc, | 700 emacs_doprnt_2 (Lisp_Object stream, CONST Bufbyte *format_nonreloc, |
712 Lisp_Object format_reloc, Bytecount format_length, int nargs, | 701 Lisp_Object format_reloc, Bytecount format_length, int nargs, |
713 const Lisp_Object *largs, ...) | 702 CONST Lisp_Object *largs, ...) |
714 { | 703 { |
715 va_list vargs; | 704 va_list vargs; |
716 Bytecount val; | 705 Bytecount val; |
717 va_start (vargs, largs); | 706 va_start (vargs, largs); |
718 val = emacs_doprnt_1 (stream, format_nonreloc, format_reloc, | 707 val = emacs_doprnt_1 (stream, format_nonreloc, format_reloc, |
741 | 730 |
742 DO NOT pass the data from a Lisp string as the FORMAT_NONRELOC | 731 DO NOT pass the data from a Lisp string as the FORMAT_NONRELOC |
743 parameter, because this function can cause GC. */ | 732 parameter, because this function can cause GC. */ |
744 | 733 |
745 Bytecount | 734 Bytecount |
746 emacs_doprnt_c (Lisp_Object stream, const Bufbyte *format_nonreloc, | 735 emacs_doprnt_c (Lisp_Object stream, CONST Bufbyte *format_nonreloc, |
747 Lisp_Object format_reloc, Bytecount format_length, | 736 Lisp_Object format_reloc, Bytecount format_length, |
748 ...) | 737 ...) |
749 { | 738 { |
750 int val; | 739 int val; |
751 va_list vargs; | 740 va_list vargs; |
758 } | 747 } |
759 | 748 |
760 /* Like emacs_doprnt_c but the args come in va_list format. */ | 749 /* Like emacs_doprnt_c but the args come in va_list format. */ |
761 | 750 |
762 Bytecount | 751 Bytecount |
763 emacs_doprnt_va (Lisp_Object stream, const Bufbyte *format_nonreloc, | 752 emacs_doprnt_va (Lisp_Object stream, CONST Bufbyte *format_nonreloc, |
764 Lisp_Object format_reloc, Bytecount format_length, | 753 Lisp_Object format_reloc, Bytecount format_length, |
765 va_list vargs) | 754 va_list vargs) |
766 { | 755 { |
767 return emacs_doprnt_1 (stream, format_nonreloc, format_reloc, | 756 return emacs_doprnt_1 (stream, format_nonreloc, format_reloc, |
768 format_length, 0, 0, vargs); | 757 format_length, 0, 0, vargs); |
772 C arguments. This causes somewhat different behavior from | 761 C arguments. This causes somewhat different behavior from |
773 the above two functions (which should act like printf). | 762 the above two functions (which should act like printf). |
774 See `format' for a description of this behavior. */ | 763 See `format' for a description of this behavior. */ |
775 | 764 |
776 Bytecount | 765 Bytecount |
777 emacs_doprnt_lisp (Lisp_Object stream, const Bufbyte *format_nonreloc, | 766 emacs_doprnt_lisp (Lisp_Object stream, CONST Bufbyte *format_nonreloc, |
778 Lisp_Object format_reloc, Bytecount format_length, | 767 Lisp_Object format_reloc, Bytecount format_length, |
779 int nargs, const Lisp_Object *largs) | 768 int nargs, CONST Lisp_Object *largs) |
780 { | 769 { |
781 return emacs_doprnt_2 (stream, format_nonreloc, format_reloc, | 770 return emacs_doprnt_2 (stream, format_nonreloc, format_reloc, |
782 format_length, nargs, largs); | 771 format_length, nargs, largs); |
783 } | 772 } |
784 | 773 |
785 /* Like the previous function but takes a variable number of arguments. */ | 774 /* Like the previous function but takes a variable number of arguments. */ |
786 | 775 |
787 Bytecount | 776 Bytecount |
788 emacs_doprnt_lisp_2 (Lisp_Object stream, const Bufbyte *format_nonreloc, | 777 emacs_doprnt_lisp_2 (Lisp_Object stream, CONST Bufbyte *format_nonreloc, |
789 Lisp_Object format_reloc, Bytecount format_length, | 778 Lisp_Object format_reloc, Bytecount format_length, |
790 int nargs, ...) | 779 int nargs, ...) |
791 { | 780 { |
792 va_list vargs; | 781 va_list vargs; |
793 int i; | 782 int i; |
805 /* The following four functions work like the above three but | 794 /* The following four functions work like the above three but |
806 return their output as a Lisp string instead of sending it | 795 return their output as a Lisp string instead of sending it |
807 to a stream. */ | 796 to a stream. */ |
808 | 797 |
809 Lisp_Object | 798 Lisp_Object |
810 emacs_doprnt_string_c (const Bufbyte *format_nonreloc, | 799 emacs_doprnt_string_c (CONST Bufbyte *format_nonreloc, |
811 Lisp_Object format_reloc, Bytecount format_length, | 800 Lisp_Object format_reloc, Bytecount format_length, |
812 ...) | 801 ...) |
813 { | 802 { |
814 va_list vargs; | 803 va_list vargs; |
815 Lisp_Object obj; | 804 Lisp_Object obj; |
828 Lstream_delete (XLSTREAM (stream)); | 817 Lstream_delete (XLSTREAM (stream)); |
829 return obj; | 818 return obj; |
830 } | 819 } |
831 | 820 |
832 Lisp_Object | 821 Lisp_Object |
833 emacs_doprnt_string_va (const Bufbyte *format_nonreloc, | 822 emacs_doprnt_string_va (CONST Bufbyte *format_nonreloc, |
834 Lisp_Object format_reloc, Bytecount format_length, | 823 Lisp_Object format_reloc, Bytecount format_length, |
835 va_list vargs) | 824 va_list vargs) |
836 { | 825 { |
837 /* I'm fairly sure that this function cannot actually GC. | 826 /* I'm fairly sure that this function cannot actually GC. |
838 That can only happen when the arguments to emacs_doprnt_1() are | 827 That can only happen when the arguments to emacs_doprnt_1() are |
851 Lstream_delete (XLSTREAM (stream)); | 840 Lstream_delete (XLSTREAM (stream)); |
852 return obj; | 841 return obj; |
853 } | 842 } |
854 | 843 |
855 Lisp_Object | 844 Lisp_Object |
856 emacs_doprnt_string_lisp (const Bufbyte *format_nonreloc, | 845 emacs_doprnt_string_lisp (CONST Bufbyte *format_nonreloc, |
857 Lisp_Object format_reloc, Bytecount format_length, | 846 Lisp_Object format_reloc, Bytecount format_length, |
858 int nargs, const Lisp_Object *largs) | 847 int nargs, CONST Lisp_Object *largs) |
859 { | 848 { |
860 Lisp_Object obj; | 849 Lisp_Object obj; |
861 Lisp_Object stream = make_resizing_buffer_output_stream (); | 850 Lisp_Object stream = make_resizing_buffer_output_stream (); |
862 struct gcpro gcpro1; | 851 struct gcpro gcpro1; |
863 | 852 |
871 Lstream_delete (XLSTREAM (stream)); | 860 Lstream_delete (XLSTREAM (stream)); |
872 return obj; | 861 return obj; |
873 } | 862 } |
874 | 863 |
875 Lisp_Object | 864 Lisp_Object |
876 emacs_doprnt_string_lisp_2 (const Bufbyte *format_nonreloc, | 865 emacs_doprnt_string_lisp_2 (CONST Bufbyte *format_nonreloc, |
877 Lisp_Object format_reloc, Bytecount format_length, | 866 Lisp_Object format_reloc, Bytecount format_length, |
878 int nargs, ...) | 867 int nargs, ...) |
879 { | 868 { |
880 Lisp_Object obj; | 869 Lisp_Object obj; |
881 Lisp_Object stream = make_resizing_buffer_output_stream (); | 870 Lisp_Object stream = make_resizing_buffer_output_stream (); |