113 '%f\n' printf:{ 1234.0 } on:Transcript |
113 '%f\n' printf:{ 1234.0 } on:Transcript |
114 '%f\n' printf:{ 1234.0 asShortFloat } on:Transcript |
114 '%f\n' printf:{ 1234.0 asShortFloat } on:Transcript |
115 '%f\n' printf:{ 1234.0 asLongFloat } on:Transcript |
115 '%f\n' printf:{ 1234.0 asLongFloat } on:Transcript |
116 '%f\n' printf:{ 1234.0 asQDouble } on:Transcript |
116 '%f\n' printf:{ 1234.0 asQDouble } on:Transcript |
117 " |
117 " |
|
118 ! |
|
119 |
|
120 format |
|
121 " |
|
122 Format specifier: |
|
123 |
|
124 required: leading '%' |
|
125 optional: '-' (POSIX refers to this as the <<flags>>) |
|
126 optional: positive number or '*' (POSIX <<width>>) |
|
127 optional: period followed by positive number or * (POSIX <<precision>>) |
|
128 optional: an h or l to indicate size of data (POSIX <<length>>) |
|
129 required: character describing output behavior (POSIX <<conversion specifier>>) |
|
130 |
|
131 Various implementations of printf have added different functionality. |
|
132 |
|
133 ANSI standards up through C99: |
|
134 |
|
135 more flags '+' ' ' '0' '#' |
|
136 more lengths 'L' 'hh' 'll' 'j' 'z' 't' |
|
137 more conversions 'F' 'a' 'A' 'n' |
|
138 |
|
139 The POSIX specification of printf added: |
|
140 |
|
141 positional parameters to identify argument indices |
|
142 more flags ''' (single quote) |
|
143 more conversions 'C' 'S' |
|
144 clarifications regarding corner cases and 'undefined behavior' |
|
145 |
|
146 BSD implementations added: |
|
147 |
|
148 more lengths 'q' |
|
149 more conversions 'D' 'U' 'O' |
|
150 |
|
151 glibc (GNU) added: |
|
152 |
|
153 more lengths 'Z' |
|
154 more conversions 'm' |
|
155 |
|
156 Windows C Runtime (CRT) added: |
|
157 |
|
158 more lengths 'I' 'I32' 'I64' 'w' |
|
159 |
|
160 glibc and CRT both added 'Z'. |
|
161 glibc uses 'Z' for the length size_t. |
|
162 CRT uses Z as a conversion for length-prefixed strings. |
|
163 This implementation takes the former approach, handling 'Z' in the same way as 'z'. |
|
164 |
|
165 BSD and IBM C library both added 'D'. |
|
166 BSD uses D as a conversion, namely as an alias of 'ld'. |
|
167 IBM uses 'D' for the length for _Decimal64, a decimal floating point type, in accordance with ISO/IEC TR 24732. |
|
168 This implementation takes the former approach. |
|
169 |
|
170 This implementation also adds new conversions: |
|
171 |
|
172 'b' and 'B' for binary (base-2) integer renderings |
|
173 'y' and 'Y' for true/false and yes/no Boolean conversions |
|
174 'J' for JSON |
|
175 'T' and 'V' for JS typeof and valueOf inspection |
|
176 |
|
177 Conversions (upper case same as lower case): |
|
178 'a' (not implemented) base-2 floating point exp form |
|
179 'b' binary (base 2) |
|
180 'c' character or (first char of string) |
|
181 'd' character or (first char of string) |
|
182 'e' base-10 floating point exp form (scientific) |
|
183 'f' base-10 floating point decimal form (non-scientific) |
|
184 'g' 'e' or 'f', whichever looks more appropriate (based on value) |
|
185 'i' integer (alias for 'd') |
|
186 'j' (not implemented) JSON format |
|
187 'n' (not implemented) stores number of characters written into arg |
|
188 'o' base-8 octal |
|
189 'p' (not implemented) pointer |
|
190 's' string |
|
191 't' type (i.e. class name) |
|
192 'u' (not implemented) unsigned (negative values are converted) |
|
193 'v' (not implemented) store string |
|
194 'x' base-16 hex |
|
195 |
|
196 Parameter selection (not implemented): |
|
197 |
|
198 <n>$ take n'th parameter |
|
199 |
|
200 Dynamic width/precision (consumed in order as presented): |
|
201 |
|
202 * take width/parameter from next argument |
|
203 |
|
204 PrintfScanf printf:'|%s|' arguments:{ 'abc' } -> '|abc|' |
|
205 PrintfScanf printf:'|%5s|' arguments:{ 'abc' } -> '| abc|' |
|
206 PrintfScanf printf:'|%*s|' arguments:{ 5 . 'abc' } -> '| abc|' |
|
207 |
|
208 PrintfScanf printf:'|%8f|' arguments:{ 1.234 } -> '| 1.234|' |
|
209 PrintfScanf printf:'|%*f|' arguments:{ 8 . 1.234 } -> '| 1.234|' |
|
210 |
|
211 |
|
212 Negative width will fill at the right: |
|
213 |
|
214 PrintfScanf printf:'|%5s|' arguments:{ 'abc' } -> '| abc|' |
|
215 PrintfScanf printf:'|%-5s|' arguments:{ 'abc' } -> '|abc |' |
|
216 PrintfScanf printf:'|%-*s|' arguments:{ 5 . 'abc' } -> '|abc |' |
|
217 PrintfScanf printf:'|%*s|' arguments:{ -5 . 'abc' } -> '|abc |' |
|
218 |
|
219 PrintfScanf printf:'|%*f|' arguments:{ -8 . 1.234 } -> '|1.234 |' |
|
220 PrintfScanf printf:'|%-8f|' arguments:{ 1.234 } -> '|1.234 |' |
|
221 PrintfScanf printf:'|%-*f|' arguments:{ 8 . 1.234 } -> '|1.234 |' |
|
222 PrintfScanf printf:'|%-*f|' arguments:{ -8 . 1.234 } -> '|1.234 |' |
|
223 |
|
224 " |
118 ! ! |
225 ! ! |
119 |
226 |
120 !PrintfScanf class methodsFor:'instance creation'! |
227 !PrintfScanf class methodsFor:'instance creation'! |
121 |
228 |
122 new |
229 new |
187 pound := true. |
296 pound := true. |
188 formatStream next. |
297 formatStream next. |
189 char := formatStream peek |
298 char := formatStream peek |
190 ]. |
299 ]. |
191 |
300 |
|
301 "/ possibly a width |
192 char == $* ifTrue:[ |
302 char == $* ifTrue:[ |
193 width := nextArg value. |
303 width := nextArg value. |
|
304 width isInteger ifFalse:[ |
|
305 self error:'non integer width argument in printf' |
|
306 ]. |
|
307 width < 0 ifTrue:[ |
|
308 ljust := true. |
|
309 width := width negated |
|
310 ]. |
194 formatStream next. |
311 formatStream next. |
195 char := formatStream peek |
312 char := formatStream peek |
196 ]. |
313 ]. |
197 |
314 |
198 char isDigit ifTrue:[ |
315 char isDigit ifTrue:[ |
199 char == $0 ifTrue: [pad := $0]. |
316 char == $0 ifTrue: [pad := $0]. |
200 width := Integer readFrom: formatStream. |
317 width := Integer readFrom: formatStream onError:0. |
201 char := formatStream peek |
318 char := formatStream peek |
202 ]. |
319 ]. |
203 |
320 |
|
321 "/ precision separator |
|
322 |
204 char == $. ifTrue:[ |
323 char == $. ifTrue:[ |
205 formatStream next. char := formatStream peek. |
324 formatStream next. char := formatStream peek. |
206 char == $* |
325 char == $* ifTrue: [ |
207 ifTrue: [precision := nextArg value. formatStream next.] |
326 precision := nextArg value. |
208 ifFalse: [precision := Integer readFrom: formatStream.]. |
327 precision isInteger ifFalse:[ |
|
328 self error:'non integer precision argument in printf' |
|
329 ]. |
|
330 formatStream next. |
|
331 ] ifFalse: [ |
|
332 precision := Integer readFrom: formatStream. |
|
333 ]. |
209 char := formatStream peek |
334 char := formatStream peek |
210 ]. |
335 ]. |
211 |
336 |
212 char == $l ifTrue:[ |
337 char == $l ifTrue:[ |
213 "Ignore long specifier." |
338 "Ignore long specifier." |
295 ljust ifTrue: [outStream nextPutAll: (arg copyFrom: 1 to: precision)]. |
420 ljust ifTrue: [outStream nextPutAll: (arg copyFrom: 1 to: precision)]. |
296 width - precision timesRepeat: [outStream nextPut: pad]. |
421 width - precision timesRepeat: [outStream nextPut: pad]. |
297 ljust ifFalse: [outStream nextPutAll: (arg copyFrom: 1 to: precision)]. |
422 ljust ifFalse: [outStream nextPutAll: (arg copyFrom: 1 to: precision)]. |
298 ^ formatStream next |
423 ^ formatStream next |
299 |
424 |
300 "Modified (comment): / 19-06-2017 / 15:46:33 / cg" |
425 "Modified: / 20-06-2017 / 15:26:02 / cg" |
301 ! |
426 ! |
302 |
427 |
303 printf:formatString argument:arg |
428 printf:formatString argument:arg |
304 "Format and print the receiver with <arg> formatted in C style, |
429 "Format and print the receiver with <arg> formatted in C style, |
305 as described in the UTek manual page for printf(3)." |
430 as described in the UTek manual page for printf(3)." |
476 self printf:'%20.10f\n' on:Transcript arguments: { 0.0 log10 } |
601 self printf:'%20.10f\n' on:Transcript arguments: { 0.0 log10 } |
477 self printf:'%20.10f\n' on:Transcript arguments: { 0.0 asShortFloat log10 } |
602 self printf:'%20.10f\n' on:Transcript arguments: { 0.0 asShortFloat log10 } |
478 self printf:'%20.10f\n' on:Transcript arguments: { 0.0 asLongFloat log10 } |
603 self printf:'%20.10f\n' on:Transcript arguments: { 0.0 asLongFloat log10 } |
479 self printf:'%20.10f\n' on:Transcript arguments: { 0.0 asQDouble log10 } |
604 self printf:'%20.10f\n' on:Transcript arguments: { 0.0 asQDouble log10 } |
480 |
605 |
481 self printf:'%20.10f\n' on:Transcript arguments: { -1.0 log10 } |
606 self printf:'%20.10f\n' on:Transcript arguments: { DomainError ignoreIn:[ -1.0 log10 ] } |
482 self printf:'%20.10f\n' on:Transcript arguments: { -1.0 asShortFloat log10 } |
607 self printf:'%20.10f\n' on:Transcript arguments: { DomainError ignoreIn:[ -1.0 asShortFloat log10 ] } |
483 self printf:'%20.10f\n' on:Transcript arguments: { -1.0 asLongFloat log10 } |
608 self printf:'%20.10f\n' on:Transcript arguments: { DomainError ignoreIn:[ -1.0 asLongFloat log10] } |
484 self printf:'%20.10f\n' on:Transcript arguments: { -1.0 asQDouble log10 } |
609 self printf:'%20.10f\n' on:Transcript arguments: { DomainError ignoreIn:[ -1.0 asQDouble log10] } |
|
610 |
|
611 self printf:'%10s\n' on:Transcript arguments:{ 'hello' } |
|
612 self printf:'%*s\n' on:Transcript arguments:{ 10 . 'hello' } |
485 " |
613 " |
486 |
614 |
487 |absVal exp x fuzz i| |
615 |absVal exp x fuzz i| |
488 |
616 |
489 aFloat isNaN ifTrue:[ |
617 aFloat isNaN ifTrue:[ |