comparison src/doprnt.c @ 448:3078fd1074e8 r21-2-39

Import from CVS: tag r21-2-39
author cvs
date Mon, 13 Aug 2007 11:38:25 +0200
parents 1ccc32a20af4
children 183866b06e0b
comparison
equal deleted inserted replaced
447:4fc5f13f3bd3 448:3078fd1074e8
85 typedef struct 85 typedef struct
86 { 86 {
87 Dynarr_declare (union printf_arg); 87 Dynarr_declare (union printf_arg);
88 } printf_arg_dynarr; 88 } printf_arg_dynarr;
89 89
90 /* Append STRING (of length LEN) to STREAM. MINLEN is the minimum field 90 /* Append STRING (of length LEN bytes) to STREAM.
91 width. If MINUS_FLAG is set, left-justify the string in its field; 91 MINLEN is the minimum field width.
92 otherwise, right-justify. If ZERO_FLAG is set, pad with 0's; otherwise 92 If MINUS_FLAG is set, left-justify the string in its field;
93 pad with spaces. If MAXLEN is non-negative, the string is first 93 otherwise, right-justify.
94 truncated to that many character. 94 If ZERO_FLAG is set, pad with 0's; otherwise pad with spaces.
95 If MAXLEN is non-negative, the string is first truncated on the
96 right to that many characters.
95 97
96 Note that MINLEN and MAXLEN are Charcounts but LEN is a Bytecount. */ 98 Note that MINLEN and MAXLEN are Charcounts but LEN is a Bytecount. */
97 99
98 static void 100 static void
99 doprnt_1 (Lisp_Object stream, const Bufbyte *string, Bytecount len, 101 doprnt_1 (Lisp_Object stream, const Bufbyte *string, Bytecount len,
100 Charcount minlen, Charcount maxlen, int minus_flag, int zero_flag) 102 Charcount minlen, Charcount maxlen, int minus_flag, int zero_flag)
101 { 103 {
102 Charcount cclen;
103 Bufbyte pad;
104 Lstream *lstr = XLSTREAM (stream); 104 Lstream *lstr = XLSTREAM (stream);
105 105 Charcount cclen = bytecount_to_charcount (string, len);
106 cclen = bytecount_to_charcount (string, len); 106 int to_add = minlen - cclen;
107
108 if (zero_flag)
109 pad = '0';
110 else
111 pad = ' ';
112 107
113 /* Padding at beginning to right-justify ... */ 108 /* Padding at beginning to right-justify ... */
114 if (minlen > cclen && !minus_flag) 109 if (!minus_flag)
115 { 110 while (to_add-- > 0)
116 int to_add = minlen - cclen; 111 Lstream_putc (lstr, zero_flag ? '0' : ' ');
117 while (to_add > 0) 112
118 { 113 if (0 <= maxlen && maxlen < cclen)
119 Lstream_putc (lstr, pad); 114 len = charcount_to_bytecount (string, maxlen);
120 to_add--;
121 }
122 }
123
124 if (maxlen >= 0)
125 len = charcount_to_bytecount (string, min (maxlen, cclen));
126 Lstream_write (lstr, string, len); 115 Lstream_write (lstr, string, len);
127 116
128 /* Padding at end to left-justify ... */ 117 /* Padding at end to left-justify ... */
129 if (minlen > cclen && minus_flag) 118 if (minus_flag)
130 { 119 while (to_add-- > 0)
131 int to_add = minlen - cclen; 120 Lstream_putc (lstr, zero_flag ? '0' : ' ');
132 while (to_add > 0)
133 {
134 Lstream_putc (lstr, pad);
135 to_add--;
136 }
137 }
138 } 121 }
139 122
140 static const Bufbyte * 123 static const Bufbyte *
141 parse_off_posnum (const Bufbyte *start, const Bufbyte *end, int *returned_num) 124 parse_off_posnum (const Bufbyte *start, const Bufbyte *end, int *returned_num)
142 { 125 {
608 doprnt_1 (stream, charbuf, charlen, spec->minwidth, 591 doprnt_1 (stream, charbuf, charlen, spec->minwidth,
609 -1, spec->minus_flag, spec->zero_flag); 592 -1, spec->minus_flag, spec->zero_flag);
610 } 593 }
611 else 594 else
612 { 595 {
613 char text_to_print[500]; 596 /* ASCII Decimal representation uses 2.4 times as many
597 bits as machine binary. */
598 char *text_to_print =
599 alloca_array (char, 32 +
600 max (spec->minwidth,
601 max (sizeof (double), sizeof (long)) * 3 +
602 max (spec->precision, 0)));
614 char constructed_spec[100]; 603 char constructed_spec[100];
615 char *p = constructed_spec; 604 char *p = constructed_spec;
616 605
617 /* Partially reconstruct the spec and use sprintf() to 606 /* Mostly reconstruct the spec and use sprintf() to
618 format the string. */ 607 format the string. */
619
620 /* Make sure nothing stupid happens */
621 /* DO NOT REMOVE THE (int) CAST! Incorrect results will
622 follow! */
623 spec->precision = min (spec->precision,
624 (int) (sizeof (text_to_print) - 50));
625 608
626 *p++ = '%'; 609 *p++ = '%';
627 if (spec->plus_flag) *p++ = '+'; 610 if (spec->plus_flag) *p++ = '+';
628 if (spec->space_flag) *p++ = ' '; 611 if (spec->space_flag) *p++ = ' ';
629 if (spec->number_flag) *p++ = '#'; 612 if (spec->number_flag) *p++ = '#';
630 613 if (spec->minus_flag) *p++ = '-';
631 if (spec->precision >= 0 && !spec->minwidth) 614 if (spec->zero_flag) *p++ = '0';
615
616 if (spec->minwidth >= 0)
617 p = long_to_string (p, spec->minwidth);
618 if (spec->precision >= 0)
632 { 619 {
633 *p++ = '.'; 620 *p++ = '.';
634 p = long_to_string (p, spec->precision); 621 p = long_to_string (p, spec->precision);
635 } 622 }
636 623
637 /* sprintf the mofo */
638 /* we have to use separate calls to sprintf(), rather than
639 a single big conditional, because of the different types
640 of the arguments */
641 if (strchr (double_converters, ch)) 624 if (strchr (double_converters, ch))
642 { 625 {
643 *p++ = ch; 626 *p++ = ch;
644 *p++ = '\0'; 627 *p++ = '\0';
645 sprintf (text_to_print, constructed_spec, arg.d); 628 sprintf (text_to_print, constructed_spec, arg.d);
646 } 629 }
647 else 630 else
648 { 631 {
649 if (spec->zero_flag && spec->minwidth) 632 *p++ = 'l'; /* Always use longs with sprintf() */
650 sprintf (p, "0%dl%c", spec->minwidth, ch); 633 *p++ = ch;
651 else 634 *p++ = '\0';
652 sprintf (p, "l%c", ch);
653 635
654 if (strchr (unsigned_int_converters, ch)) 636 if (strchr (unsigned_int_converters, ch))
655 sprintf (text_to_print, constructed_spec, arg.ul); 637 sprintf (text_to_print, constructed_spec, arg.ul);
656 else 638 else
657 sprintf (text_to_print, constructed_spec, arg.l); 639 sprintf (text_to_print, constructed_spec, arg.l);
658 } 640 }
659 641
660 doprnt_1 (stream, (Bufbyte *) text_to_print, 642 doprnt_1 (stream, (Bufbyte *) text_to_print,
661 strlen (text_to_print), 643 strlen (text_to_print), 0, -1, 0, 0);
662 spec->minwidth, -1, spec->minus_flag, spec->zero_flag);
663 } 644 }
664 } 645 }
665 } 646 }
666 647
667 /* #### will not get freed if error */ 648 /* #### will not get freed if error */