PrintfScanf.st
changeset 4416 40f676e88785
parent 4401 a29669a0e2a1
child 4417 01b4de1f0b01
equal deleted inserted replaced
4415:2b984cf54494 4416:40f676e88785
    11 
    11 
    12 !PrintfScanf class methodsFor:'documentation'!
    12 !PrintfScanf class methodsFor:'documentation'!
    13 
    13 
    14 documentation
    14 documentation
    15 "   
    15 "   
    16     Contributed by Jan Steinman donated to the
    16     Contributed by Jan Steinman donated to the community in 1989.
    17     community in 1989.
       
    18 
    17 
    19     Provided AS-IS - no warranty, use at your own risk.
    18     Provided AS-IS - no warranty, use at your own risk.
    20 
    19 
    21     Original comment:
    20     Original comment:
    22 
    21 
    38 
    37 
    39     Jan Steinman - N7JDB
    38     Jan Steinman - N7JDB
    40     Tektronix Electronic Systems Laboratory
    39     Tektronix Electronic Systems Laboratory
    41     Box 500, MS 50-370, Beaverton, OR 97077
    40     Box 500, MS 50-370, Beaverton, OR 97077
    42     (w)503/627-5881 (h)503/657-7703
    41     (w)503/627-5881 (h)503/657-7703
       
    42 
       
    43     changes:
       
    44         slight changes to make it work with higher precision real numbers
       
    45         (i.e. asking for the precision instead of hard-coding it)
    43 "
    46 "
    44 !
    47 !
    45 
    48 
    46 examples
    49 examples
    47 "
    50 "
    48     self new printf:'%#x %#X %03o%*.*s' arguments: #(16rABCD 16rEF 5 9 5 ''ghijklmn'') 
    51     self printf:'%#x %#X %03o%*.*s' arguments: #(16rABCD 16rEF 5 9 5 'ghijklmn')
    49 
    52             -> '0xabcd 0xEF 005    ghijk'
    50     self new printf:'%- 10.4s%.2e' arguments: { 'abcdefghijkl' . Float pi }  
    53 
    51 
    54     self printf:'%- 10.4s%.2e' arguments: { 'abcdefghijkl' . Float pi }  
    52     self new printf:'%8.3f' arguments: { 200 sqrt negated }
    55             -> ' abcd      3.14e0'
       
    56             
       
    57     self printf:'%8.3f' arguments: { 200 sqrt negated }
       
    58             -> ' -14.142'
       
    59 
    53     self printf:'%8.3f' on:Transcript arguments: { 200 sqrt negated }
    60     self printf:'%8.3f' on:Transcript arguments: { 200 sqrt negated }
    54     self printf:'%10.4f' on:Transcript arguments: { 200 sqrt negated }
    61     self printf:'%10.4f' on:Transcript arguments: { 200 sqrt negated }
    55     self printf:'%20.10f' on:Transcript arguments: { 200 sqrt negated }
    62     self printf:'%20.10f' on:Transcript arguments: { 200 sqrt negated }
    56 
    63 
    57     self printf:'%20.10f' on:Transcript arguments: { 1.234567890123456789f  }
    64     self printf:'%20.10f' on:Transcript arguments: { 1.234567890123456789f  }
    58     self printf:'%20.10f' on:Transcript arguments: { 1.234567890123456789q  }
    65     self printf:'%20.10f' on:Transcript arguments: { 1.234567890123456789q  }
    59 
    66 
    60     self new printf:'%x' arguments: #(16r41)  
    67     self printf:'%x' arguments: #(16r41)        -> '41' 
    61     self new printf:'%#x' arguments: #(16r41)   
    68     self printf:'%#x' arguments: #(16r41)       -> '0x41'
    62     self new printf:'%d' arguments: #(16r41)  
    69     self printf:'%d' arguments: #(16r41)        -> '65'
    63     self new printf:'%b' arguments: #(16r41)  
    70     self printf:'%b' arguments: #(16r41)        -> '1000001'
    64     self new printf:'%c' arguments: #(16r41) 
    71     self printf:'%c' arguments: #(16r41)        -> 'A'
    65     self new printf:'%c' arguments: #( $A )  
    72     self printf:'%c' arguments: #( $A )         -> 'A'
    66     self new printf:'%s' arguments: #( $A )  
    73     self printf:'%s' arguments: #( $A )         -> 'A'
    67     self new printf:'%s' arguments: #( 'hello' )   
    74     self printf:'%s' arguments: #( 'hello' )    -> 'hello'
    68     self new printf:'%4s' arguments: #( 'hello' )   
    75     self printf:'%4s' arguments: #( 'hello' )   -> 'hello'
    69     self new printf:'%7s' arguments: #( 'hello' )   
    76     self printf:'%7s' arguments: #( 'hello' )   -> '  hello'
    70 
    77 
    71     self new sscanf:'%f%2s%s%s%s' fromString: '237.0 this is a test' 
    78     self sscanf:'%f%2s%s%s%s' fromString: '237.0 this is a test' 
    72 
    79             -> OrderedCollection(237.0 'th' 'is' 'is' 'a')
    73     self new sscanf:'%d%f%s' fromString: '25 54.32e-01 monday'
    80 
    74 
    81     self sscanf:'%d%f%s' fromString: '25 54.32e-01 monday'
    75     self new sscanf:'%f%*f %8[A-F0-9]%c%d 0x%x%f' fromString: '12.45 1048.73 AE40Z527 0x75BCD15 34' 
    82             -> OrderedCollection(25 5.432 'monday')
    76 
    83 
    77     '%#x %#X %03o%*.*s' printf: #(16rABCD 16rEF 5 9 5 ''ghijklmn'') 
    84     self sscanf:'%f%*f %8[A-F0-9]%c%d 0x%x%f' fromString: '12.45 1048.73 AE40Z527 0x75BCD15 34' 
       
    85             -> OrderedCollection(12.45 'AE40' 'Z' 527 123456789 34.0)
       
    86 
       
    87     '%#x %#X %03o%*.*s' printf: #(16rABCD 16rEF 5 9 5 'ghijklmn') 
       
    88             -> '0xabcd 0xEF 005    ghijk'
    78 
    89 
    79     '%- 10.4s%.2e' printf: { 'abcdefghijkl' . Float pi }  
    90     '%- 10.4s%.2e' printf: { 'abcdefghijkl' . Float pi }  
       
    91             -> ' abcd      3.14e0'
    80 
    92 
    81     '%8.3f' printf: { 200 sqrt negated }
    93     '%8.3f' printf: { 200 sqrt negated }
       
    94             -> ' -14.142'
    82 
    95 
    83     '%c' printf: #(16r41)
    96     '%c' printf: #(16r41)
       
    97             -> 'A'
    84 
    98 
    85     '%f%2s%s%s%s' sscanf: '237.0 this is a test' 
    99     '%f%2s%s%s%s' sscanf: '237.0 this is a test' 
       
   100             -> OrderedCollection(237.0 'th' 'is' 'is' 'a')
    86 
   101 
    87     '%d%f%s' sscanf: '25 54.32e-01 monday'
   102     '%d%f%s' sscanf: '25 54.32e-01 monday'
       
   103             -> OrderedCollection(25 5.432 'monday')
    88 
   104 
    89     '%f%*f %8[A-F0-9]%c%d 0x%x%f' sscanf: '12.45 1048.73 AE40Z527 0x75BCD15 34'
   105     '%f%*f %8[A-F0-9]%c%d 0x%x%f' sscanf: '12.45 1048.73 AE40Z527 0x75BCD15 34'
       
   106             -> OrderedCollection(12.45 'AE40' 'Z' 527 123456789 34.0)
    90 "
   107 "
    91 ! !
   108 ! !
    92 
   109 
    93 !PrintfScanf class methodsFor:'instance creation'!
   110 !PrintfScanf class methodsFor:'instance creation'!
    94 
   111 
    97         Singleton := self basicNew
   114         Singleton := self basicNew
    98     ].    
   115     ].    
    99     ^ Singleton
   116     ^ Singleton
   100 ! !
   117 ! !
   101 
   118 
   102 !PrintfScanf class methodsFor:'printing'!
   119 !PrintfScanf class methodsFor:'helpers'!
   103 
       
   104 printf:formatString argument:arg 
       
   105     "Format and print the receiver with <arg> formatted in C style, 
       
   106      as described in the UTek manual page for printf(3)."
       
   107 
       
   108     ^ self printf:formatString arguments:{ arg }
       
   109 
       
   110     "
       
   111      self printf:'%e' on:Transcript argument:(1.234 asShortFloat)
       
   112      self printf:'%e' on:Transcript argument:(1.234 asFloat)     
       
   113      self printf:'%e' on:Transcript argument:(1.234 asLongFloat) 
       
   114      self printf:'%e' on:Transcript argument:(1.234 asQDouble)   
       
   115      self printf:'%e' on:Transcript argument:(1.234 asInteger)   
       
   116 
       
   117      self printf:'%10e' on:Transcript argument:(1.234 asShortFloat)
       
   118      self printf:'%10e' on:Transcript argument:(1.234 asFloat)     
       
   119      self printf:'%10e' on:Transcript argument:(1.234 asLongFloat) 
       
   120      self printf:'%10e' on:Transcript argument:(1.234 asQDouble)   
       
   121      self printf:'%10e' on:Transcript argument:(1.234 asInteger)   
       
   122 
       
   123      self printf:'%010e' on:Transcript argument:(1.234 asInteger)   
       
   124      self printf:'%-10e' on:Transcript argument:(1.234 asInteger)   
       
   125 
       
   126      self printf:'%10.9f' on:Transcript argument:(1.2345 asShortFloat)
       
   127      self printf:'%10.9f' on:Transcript argument:(1.2345 asFloat)     
       
   128      self printf:'%10.9f' on:Transcript argument:(1.2345 asLongFloat) 
       
   129      self printf:'%10.9f' on:Transcript argument:(1.2345 asQDouble)   
       
   130      self printf:'%10.9f' on:Transcript argument:(1.2345 asInteger)   
       
   131     "
       
   132 
       
   133     "Created: / 16-06-2017 / 14:50:08 / cg"
       
   134 !
       
   135 
       
   136 printf:formatString arguments:args 
       
   137     "Format and print the receiver with <args> formatted in C style, 
       
   138      as described in the UTek manual page for printf(3)."
       
   139 
       
   140     ^ self new printf:formatString arguments:args
       
   141 
       
   142     "
       
   143      self printf:'%e' on:Transcript arguments:{ (1.234 asShortFloat) }
       
   144      self printf:'%e' on:Transcript arguments:{ (1.234 asFloat)      }
       
   145      self printf:'%e' on:Transcript arguments:{ (1.234 asLongFloat)  }
       
   146      self printf:'%e' on:Transcript arguments:{ (1.234 asQDouble)    }
       
   147      self printf:'%e' on:Transcript arguments:{ (1.234 asInteger)    }
       
   148 
       
   149      self printf:'%10e' on:Transcript arguments:{ (1.234 asShortFloat) }
       
   150      self printf:'%10e' on:Transcript arguments:{ (1.234 asFloat)      }
       
   151      self printf:'%10e' on:Transcript arguments:{ (1.234 asLongFloat)  }
       
   152      self printf:'%10e' on:Transcript arguments:{ (1.234 asQDouble)    }
       
   153      self printf:'%10e' on:Transcript arguments:{ (1.234 asInteger)    }
       
   154 
       
   155      self printf:'%010e' on:Transcript arguments:{ (1.234 asInteger)    }
       
   156      self printf:'%-10e' on:Transcript arguments:{ (1.234 asInteger)    }
       
   157 
       
   158      self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asShortFloat) }
       
   159      self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asFloat)      }
       
   160      self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asLongFloat)  }
       
   161      self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asQDouble)    }
       
   162      self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asInteger)    }
       
   163     "
       
   164 
       
   165     "Modified (comment): / 16-06-2017 / 10:37:44 / cg"
       
   166 !
       
   167 
       
   168 printf:formatString on:outStream argument: arg
       
   169     "Format and print formatString on <outStream> with <arg>
       
   170      formatted in C style, as described in the UTek manual page for
       
   171      printf(3).  This method is designed for producing output
       
   172      suitable for a machine."     
       
   173 
       
   174     ^ self printf:formatString on:outStream arguments:{ arg }
       
   175 
       
   176     "
       
   177      self printf:'%e' on:Transcript argument:(1.234 asShortFloat). Transcript cr.
       
   178      self printf:'%e' on:Transcript argument:(1.234 asFloat)     . Transcript cr.
       
   179      self printf:'%e' on:Transcript argument:(1.234 asLongFloat) . Transcript cr.
       
   180      self printf:'%e' on:Transcript argument:(1.234 asQDouble)   . Transcript cr.
       
   181      self printf:'%e' on:Transcript argument:(1.234 asInteger)   . Transcript cr.
       
   182 
       
   183      self printf:'%10e' on:Transcript argument:(1.234 asShortFloat). Transcript cr.
       
   184      self printf:'%10e' on:Transcript argument:(1.234 asFloat)     . Transcript cr.
       
   185      self printf:'%10e' on:Transcript argument:(1.234 asLongFloat) . Transcript cr.
       
   186      self printf:'%10e' on:Transcript argument:(1.234 asQDouble)   . Transcript cr.
       
   187      self printf:'%10e' on:Transcript argument:(1.234 asInteger)   . Transcript cr.
       
   188 
       
   189      self printf:'%010e' on:Transcript argument:(1.234 asInteger)  . Transcript cr.
       
   190      self printf:'%-10e' on:Transcript argument:(1.234 asInteger)  . Transcript cr.
       
   191 
       
   192      self printf:'%10.9f' on:Transcript argument:(1.2345 asShortFloat). Transcript cr.
       
   193      self printf:'%10.9f' on:Transcript argument:(1.2345 asFloat)     . Transcript cr.
       
   194      self printf:'%10.9f' on:Transcript argument:(1.2345 asLongFloat) . Transcript cr.
       
   195      self printf:'%10.9f' on:Transcript argument:(1.2345 asQDouble)   . Transcript cr.
       
   196      self printf:'%10.9f' on:Transcript argument:(1.2345 asInteger)   . Transcript cr.
       
   197     "
       
   198 
       
   199     "Created: / 16-06-2017 / 14:50:40 / cg"
       
   200 !
       
   201 
       
   202 printf:formatString on:outStream arguments: args
       
   203     "Format and print formatString on <outStream> with <args>
       
   204      formatted in C style, as described in the UTek manual page for
       
   205      printf(3).  This method is designed for producing output
       
   206      suitable for a machine."     
       
   207 
       
   208     ^ self new printf:formatString on:outStream arguments: args
       
   209 
       
   210     "
       
   211      self printf:'%e' on:Transcript arguments:{ (1.234 asShortFloat) }
       
   212      self printf:'%e' on:Transcript arguments:{ (1.234 asFloat)      }
       
   213      self printf:'%e' on:Transcript arguments:{ (1.234 asLongFloat)  }
       
   214      self printf:'%e' on:Transcript arguments:{ (1.234 asQDouble)    }
       
   215      self printf:'%e' on:Transcript arguments:{ (1.234 asInteger)    }
       
   216 
       
   217      self printf:'%10e' on:Transcript arguments:{ (1.234 asShortFloat) }
       
   218      self printf:'%10e' on:Transcript arguments:{ (1.234 asFloat)      }
       
   219      self printf:'%10e' on:Transcript arguments:{ (1.234 asLongFloat)  }
       
   220      self printf:'%10e' on:Transcript arguments:{ (1.234 asQDouble)    }
       
   221      self printf:'%10e' on:Transcript arguments:{ (1.234 asInteger)    }
       
   222 
       
   223      self printf:'%010e' on:Transcript arguments:{ (1.234 asInteger)    }
       
   224      self printf:'%-10e' on:Transcript arguments:{ (1.234 asInteger)    }
       
   225 
       
   226      self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asShortFloat) }
       
   227      self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asFloat)      }
       
   228      self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asLongFloat)  }
       
   229      self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asQDouble)    }
       
   230      self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asInteger)    }
       
   231     "
       
   232 
       
   233     "Modified (comment): / 16-06-2017 / 14:51:08 / cg"
       
   234 ! !
       
   235 
       
   236 !PrintfScanf class methodsFor:'scanning'!
       
   237 
       
   238 scanf:formatString fromStream:dataStream 
       
   239     "Return a Collection of objects found in the Character Stream
       
   240      <dataStream> as interpreted according to the receiver.  The
       
   241      receiver is assumed to be a conversion control string as
       
   242      specified in the UTek manual page for scanf(3)."
       
   243 
       
   244    ^ self new scanf:formatString fromStream:dataStream
       
   245 !
       
   246 
       
   247 sscanf:formatString fromString:aString 
       
   248     "Return a Collection of objects found in <string> as
       
   249      interpreted according to the receiver.  The receiver is
       
   250      assumed to be a conversion control string as specified in the
       
   251      UTek manual page for scanf(3)."
       
   252 
       
   253    ^ self new sscanf:formatString fromString:aString
       
   254 ! !
       
   255 
       
   256 !PrintfScanf methodsFor:'helpers'!
       
   257 
   120 
   258 absDecimalPrintFloat:aFloat on:aStream digits:digits 
   121 absDecimalPrintFloat:aFloat on:aStream digits:digits 
   259     "Place a string representation of the receiver on <aStream>,
   122     "Place a string representation of the receiver on <aStream>,
   260      using <digits> significant digits, using decimal notation."
   123      using <digits> significant digits, using decimal notation."
   261     
   124     
   262 "
   125     "
   263     self printf:'%20.10f' on:Transcript arguments: { 1.234567890123456789f  }
   126      self printf:'%20.10f' on:Transcript arguments: { 1.234567890123456789f  }
   264     self printf:'%20.10f' on:Transcript arguments: { 1.234567890123456789q  }
   127      self printf:'%20.10f' on:Transcript arguments: { 1.234567890123456789q  }
   265 "
   128     "
   266 
   129 
   267     |absVal exp x fuzz i|
   130     |absVal exp x fuzz i|
   268 
   131 
   269     absVal := aFloat abs.
   132     absVal := aFloat abs.
   270 
   133 
   271     "x is myself normalized to (1.0, 10.0), exp is my exponent"
   134     "x is myself normalized to (1.0, 10.0), exp is my exponent"
   272     exp := absVal < 1.0 
   135     exp := absVal < 1.0 
   273             ifTrue:[ 
   136             ifTrue:[ 
   274                 (10.0 / absVal) log floor asInteger negated ] 
   137                 (10.0 / absVal) log10 floor asInteger negated ] 
   275             ifFalse:[
   138             ifFalse:[
   276                 absVal log floor asInteger].
   139                 absVal log10 floor asInteger].
   277     x := absVal / (10.0 raisedTo:exp).
   140     x := absVal / (10.0 raisedTo:exp).
   278     fuzz := 10.0 raisedTo:1 - digits.
   141     fuzz := 10.0 raisedTo:1 - digits.
       
   142     "round the last digit to be printed"
   279     x := 0.5 * fuzz + x.
   143     x := 0.5 * fuzz + x.
   280     x >= 10.0 ifTrue:[ 
   144     x >= 10.0 ifTrue:[ 
   281         "check if rounding has unnormalized x" 
   145         "check if rounding has unnormalized x" 
   282         x := x / 10.0.
   146         x := x / 10.0.
   283         exp := exp + 1
   147         exp := exp + 1
   308         exp = -1 ifTrue:[
   172         exp = -1 ifTrue:[
   309             aStream nextPut:$.
   173             aStream nextPut:$.
   310         ]
   174         ]
   311     ]
   175     ]
   312 
   176 
   313     "Modified: / 17-06-2017 / 03:41:44 / cg"
   177     "Modified (comment): / 19-06-2017 / 14:56:40 / cg"
   314 !
   178 !
   315 
   179 
   316 absPrintFloat:aFloat on:aStream digits:digits 
   180 absPrintFloat:aFloat on:aStream digits:digits 
   317     "Place a string representation of the receiver on <aStream>,
   181     "Place a string representation of the receiver on <aStream>,
   318      using <digits> significant digits."
   182      using <digits> significant digits."
   319     
   183     
   320     (aFloat < 1.0e6 and:[ aFloat > 1.0e-4 ]) ifTrue:[
   184     (aFloat < 1.0e6 and:[ aFloat > 1.0e-4 ]) ifTrue:[
   321         self 
   185         self absDecimalPrintFloat:aFloat on:aStream digits:digits
   322             absDecimalPrintFloat:aFloat
       
   323             on:aStream
       
   324             digits:digits
       
   325     ] ifFalse:[
   186     ] ifFalse:[
   326         aFloat 
   187         self absScientificPrintFloat:aFloat on:aStream digits:digits
   327             absScientificPrintFloat:aFloat
       
   328             on:aStream
       
   329             digits:digits
       
   330     ]
   188     ]
   331 
   189 
   332     "Modified (comment): / 16-06-2017 / 10:25:33 / cg"
   190     "Modified: / 19-06-2017 / 15:03:40 / cg"
   333 !
   191 !
   334 
   192 
   335 absScientificPrintFloat:aFloat on:aStream digits:digits 
   193 absScientificPrintFloat:aFloat on:aStream digits:digits 
   336     "Place a string representation of the receiver on <aStream>,
   194     "Place a string representation of the receiver on <aStream>,
   337      using <digits> significant digits, using scientific notation."
   195      using <digits> significant digits, using scientific notation."
   341     absVal := aFloat abs.
   199     absVal := aFloat abs.
   342     
   200     
   343     "x is myself normalized to [1.0, 10.0), exp is my exponent"
   201     "x is myself normalized to [1.0, 10.0), exp is my exponent"
   344     exp := absVal < 1.0 
   202     exp := absVal < 1.0 
   345                 ifTrue:[
   203                 ifTrue:[
   346                     (10.0 / absVal) log floor asInteger negated]
   204                     (10.0 / absVal) log10 floor asInteger negated]
   347                 ifFalse:[
   205                 ifFalse:[
   348                     absVal log floor asInteger].
   206                     absVal log10 floor asInteger].
   349     x := absVal / (10.0 raisedTo:exp).
   207     x := absVal / (10.0 raisedTo:exp).
       
   208     "round the last digit to be printed"
   350     fuzz := 10.0 raisedTo:1 - digits.
   209     fuzz := 10.0 raisedTo:1 - digits.
   351     x := 0.5 * fuzz + x.
   210     x := 0.5 * fuzz + x.
   352     x >= 10.0 ifTrue:[ "check if rounding has unnormalized x" 
   211     x >= 10.0 ifTrue:[ "check if rounding has unnormalized x" 
   353         x := x / 10.0.
   212         x := x / 10.0.
   354         exp := exp + 1
   213         exp := exp + 1
   374         ]
   233         ]
   375     ].
   234     ].
   376     aStream nextPut:$e.
   235     aStream nextPut:$e.
   377     q printOn:aStream
   236     q printOn:aStream
   378 
   237 
   379     "Modified: / 16-06-2017 / 10:27:03 / cg"
   238     "Modified (comment): / 19-06-2017 / 14:58:53 / cg"
   380 !
   239 !
   381 
   240 
   382 formatArgCountFor:aFormatString
   241 formatArgCountFor:aFormatString
   383     "Return the number of arguments required/produced,
   242     "Return the number of arguments required/produced,
   384      if the argument is interpreted as a printf/scanf format control string."
   243      if the argument is interpreted as a printf/scanf format control string."
   401         ]
   260         ]
   402     ].
   261     ].
   403     ^ count
   262     ^ count
   404 ! !
   263 ! !
   405 
   264 
   406 !PrintfScanf methodsFor:'printing'!
   265 !PrintfScanf class methodsFor:'printing'!
   407 
   266 
   408 printArgFrom:inStream to:outStream arguments:argStream
   267 printArgFrom:formatStream to:outStream arguments:argStream
   409     "Interpret the required number of arguments from <argStream>
   268     "Interpret the required number of arguments from <argStream>
   410      according to the formatting information in <inStream>.  Place
   269      according to the formatting information in <formatStream>.  Place
   411      the interpretation on <outStream>.  The interpretation is C
   270      the interpretation on <outStream>.  The interpretation is C
   412      printf(3) style, as described in the UTek manual page for
   271      printf(3) style, as described in the UTek manual page for
   413      printf(3).  <inStream> is assumed to be positioned just past
   272      printf(3).  <formatStream> is assumed to be positioned just past
   414      $%, and a complete control string is assumed available.     
   273      $%, and a complete control string is assumed available.     
   415 
   274 
   416      Return when the conversion control string is consumed.  
   275      Return when the conversion control string is consumed.  
   417      Leave <inStream> pointing past the last character in the conversion control string.
   276      Leave <formatStream> pointing past the last character in the conversion control string.
   418 
   277 
   419      This code assumes that <inStream> is formatted according to
   278      This code assumes that <formatStream> is formatted according to
   420      specification, and error checking is minimal.  Unexpected
   279      specification, and error checking is minimal.  Unexpected
   421      results will be obtained by illegal control strings, or when
   280      results will be obtained by illegal control strings, or when
   422      argument types do not match conversion codes, but it probably
   281      argument types do not match conversion codes, but it probably
   423      won't dump core, like C does in such cases!!!!"    
   282      won't dump core, like C does in such cases!!!!"    
   424 
   283 
   427     ljust := plus := pound := false.
   286     ljust := plus := pound := false.
   428     width := 0.
   287     width := 0.
   429     "/ precision := SmallInteger maxVal.
   288     "/ precision := SmallInteger maxVal.
   430     precision := nil.
   289     precision := nil.
   431     pad := $ .
   290     pad := $ .
   432     char := inStream peek.
   291     char := formatStream peek.
   433 
   292 
   434     char == $% ifTrue:[ 
   293     char == $% ifTrue:[ 
   435         ^ outStream nextPut: inStream next
   294         ^ outStream nextPut: formatStream next
   436     ].
   295     ].
   437 
   296 
   438     char == $- ifTrue:[
   297     char == $- ifTrue:[
   439         ljust := true.  
   298         ljust := true.  
   440         inStream next.  
   299         formatStream next.  
   441         char := inStream peek
   300         char := formatStream peek
   442     ].
   301     ].
   443 
   302 
   444     char == $  ifTrue:[
   303     char == $  ifTrue:[
   445         outStream space.  
   304         outStream space.  
   446         inStream next.  
   305         formatStream next.  
   447         char := inStream peek
   306         char := formatStream peek
   448     ].
   307     ].
   449 
   308 
   450     char == $+ ifTrue:[
   309     char == $+ ifTrue:[
   451         plus := true.  
   310         plus := true.  
   452         inStream next. 
   311         formatStream next. 
   453         char := inStream peek
   312         char := formatStream peek
   454     ].
   313     ].
   455 
   314 
   456     char == $# ifTrue:[
   315     char == $# ifTrue:[
   457         pound := true.  
   316         pound := true.  
   458         inStream next.  
   317         formatStream next.  
   459         char := inStream peek
   318         char := formatStream peek
   460     ].
   319     ].
   461 
   320 
   462     char == $* ifTrue:[
   321     char == $* ifTrue:[
   463         width := argStream next.  
   322         width := argStream next.  
   464         inStream next.  
   323         formatStream next.  
   465         char := inStream peek
   324         char := formatStream peek
   466     ].
   325     ].
   467 
   326 
   468     char isDigit ifTrue:[
   327     char isDigit ifTrue:[
   469         char == $0 ifTrue: [pad := $0].
   328         char == $0 ifTrue: [pad := $0].
   470         width := Integer readFrom: inStream.  
   329         width := Integer readFrom: formatStream.  
   471         char := inStream peek
   330         char := formatStream peek
   472     ].
   331     ].
   473 
   332 
   474     char == $. ifTrue:[
   333     char == $. ifTrue:[
   475         inStream next.  char := inStream peek.
   334         formatStream next.  char := formatStream peek.
   476         char == $*
   335         char == $*
   477             ifTrue: [precision := argStream next.  inStream next.]
   336             ifTrue: [precision := argStream next.  formatStream next.]
   478             ifFalse: [precision := Integer readFrom: inStream.].
   337             ifFalse: [precision := Integer readFrom: formatStream.].
   479         char := inStream peek
   338         char := formatStream peek
   480     ].
   339     ].
   481 
   340 
   482     char == $l ifTrue:[
   341     char == $l ifTrue:[
   483         "Ignore long specifier."
   342         "Ignore long specifier."
   484         inStream next.  char := inStream peek
   343         formatStream next.  char := formatStream peek
   485     ].
   344     ].
   486 
   345 
   487     ('feg' includes: char) ifTrue:[
   346     ('feg' includes: char) ifTrue:[
   488         arg := argStream next.
   347         arg := argStream next.
   489         arg isLimitedPrecisionReal ifTrue:[
   348         arg isLimitedPrecisionReal ifTrue:[
   494         ].    
   353         ].    
   495         argString := WriteStream on:''.
   354         argString := WriteStream on:''.
   496         char == $g ifTrue: [ 
   355         char == $g ifTrue: [ 
   497             self absPrintFloat:arg on: argString digits: precision + 1 ].
   356             self absPrintFloat:arg on: argString digits: precision + 1 ].
   498         char == $f ifTrue: [ 
   357         char == $f ifTrue: [ 
   499             self absDecimalPrintFloat:arg on: argString digits: precision + arg abs log + 1].
   358             self absDecimalPrintFloat:arg on: argString digits: precision + arg abs log10 + 1].
   500         char == $e ifTrue: [
   359         char == $e ifTrue: [
   501             self absScientificPrintFloat:arg on: argString digits: precision + 1].
   360             self absScientificPrintFloat:arg on: argString digits: precision + 1].
   502         argString := argString contents.
   361         argString := argString contents.
   503         arg < 0
   362         arg < 0
   504             ifTrue: [argString := '-', argString]
   363             ifTrue: [argString := '-', argString]
   516                         timesRepeat:[
   375                         timesRepeat:[
   517                             argString := argString, '0']]].
   376                             argString := argString, '0']]].
   518         ljust ifTrue: [outStream nextPutAll: argString].
   377         ljust ifTrue: [outStream nextPutAll: argString].
   519         width - argString size timesRepeat: [outStream nextPut: pad].
   378         width - argString size timesRepeat: [outStream nextPut: pad].
   520         ljust ifFalse: [outStream nextPutAll: argString].
   379         ljust ifFalse: [outStream nextPutAll: argString].
   521         ^inStream next
   380         ^ formatStream next
   522     ].
   381     ].
   523 
   382 
   524     char == $c ifTrue:[
   383     char == $c ifTrue:[
   525         arg := argStream next asCharacter asString
   384         arg := argStream next asCharacter asString
   526     ].
   385     ].
   563 
   422 
   564     precision := precision ? arg size.
   423     precision := precision ? arg size.
   565     ljust ifTrue: [outStream nextPutAll: (arg copyFrom: 1 to: precision)].
   424     ljust ifTrue: [outStream nextPutAll: (arg copyFrom: 1 to: precision)].
   566     width - precision timesRepeat: [outStream nextPut: pad].
   425     width - precision timesRepeat: [outStream nextPut: pad].
   567     ljust ifFalse: [outStream nextPutAll: (arg copyFrom: 1 to: precision)].
   426     ljust ifFalse: [outStream nextPutAll: (arg copyFrom: 1 to: precision)].
   568     ^ inStream next
   427     ^ formatStream next
   569 
   428 
   570     "Modified: / 17-06-2017 / 03:38:35 / cg"
   429     "Modified (comment): / 19-06-2017 / 15:20:11 / cg"
   571 !
   430 !
   572 
   431 
   573 printf:aString arguments:args 
   432 printf:formatString argument:arg 
       
   433     "Format and print the receiver with <arg> formatted in C style, 
       
   434      as described in the UTek manual page for printf(3)."
       
   435 
       
   436     ^ self printf:formatString arguments:{ arg }
       
   437 
       
   438     "
       
   439      self printf:'%e' on:Transcript argument:(1.234 asShortFloat)
       
   440      self printf:'%e' on:Transcript argument:(1.234 asFloat)     
       
   441      self printf:'%e' on:Transcript argument:(1.234 asLongFloat) 
       
   442      self printf:'%e' on:Transcript argument:(1.234 asQDouble)   
       
   443      self printf:'%e' on:Transcript argument:(1.234 asInteger)   
       
   444 
       
   445      self printf:'%10e' on:Transcript argument:(1.234 asShortFloat)
       
   446      self printf:'%10e' on:Transcript argument:(1.234 asFloat)     
       
   447      self printf:'%10e' on:Transcript argument:(1.234 asLongFloat) 
       
   448      self printf:'%10e' on:Transcript argument:(1.234 asQDouble)   
       
   449      self printf:'%10e' on:Transcript argument:(1.234 asInteger)   
       
   450 
       
   451      self printf:'%010e' on:Transcript argument:(1.234 asInteger)   
       
   452      self printf:'%-10e' on:Transcript argument:(1.234 asInteger)   
       
   453 
       
   454      self printf:'%10.9f' on:Transcript argument:(1.2345 asShortFloat)
       
   455      self printf:'%10.9f' on:Transcript argument:(1.2345 asFloat)     
       
   456      self printf:'%10.9f' on:Transcript argument:(1.2345 asLongFloat) 
       
   457      self printf:'%10.9f' on:Transcript argument:(1.2345 asQDouble)   
       
   458      self printf:'%10.9f' on:Transcript argument:(1.2345 asInteger)   
       
   459     "
       
   460 
       
   461     "Created: / 16-06-2017 / 14:50:08 / cg"
       
   462 !
       
   463 
       
   464 printf:formatString arguments:args 
   574     "Format and print the receiver with <args> formatted in C style, 
   465     "Format and print the receiver with <args> formatted in C style, 
   575      as described in the UTek manual page for printf(3).
   466      as described in the UTek manual page for printf(3)."
   576      Returns the formatted printString."
   467 
   577     
       
   578     |aStream|
   468     |aStream|
   579 
   469 
   580     aStream := WriteStream on:(aString species new:100).
   470     aStream := WriteStream on:(formatString species new:100).
   581     self printf:aString on:aStream arguments:args.
   471     self printf:formatString on:aStream arguments:args.
   582     ^ aStream contents
   472     ^ aStream contents
   583 
   473 
   584     "
   474     "
   585      self new printf:'%d %x' arguments:#(1234 45054) 
   475      self printf:'%e' on:Transcript arguments:{ (1.234 asShortFloat) }
   586     "
   476      self printf:'%e' on:Transcript arguments:{ (1.234 asFloat)      }
   587 
   477      self printf:'%e' on:Transcript arguments:{ (1.234 asLongFloat)  }
   588     "Modified (comment): / 16-06-2017 / 15:09:01 / cg"
   478      self printf:'%e' on:Transcript arguments:{ (1.234 asQDouble)    }
       
   479      self printf:'%e' on:Transcript arguments:{ (1.234 asInteger)    }
       
   480 
       
   481      self printf:'%10e' on:Transcript arguments:{ (1.234 asShortFloat) }
       
   482      self printf:'%10e' on:Transcript arguments:{ (1.234 asFloat)      }
       
   483      self printf:'%10e' on:Transcript arguments:{ (1.234 asLongFloat)  }
       
   484      self printf:'%10e' on:Transcript arguments:{ (1.234 asQDouble)    }
       
   485      self printf:'%10e' on:Transcript arguments:{ (1.234 asInteger)    }
       
   486 
       
   487      self printf:'%010e' on:Transcript arguments:{ (1.234 asInteger)    }
       
   488      self printf:'%-10e' on:Transcript arguments:{ (1.234 asInteger)    }
       
   489 
       
   490      self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asShortFloat) }
       
   491      self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asFloat)      }
       
   492      self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asLongFloat)  }
       
   493      self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asQDouble)    }
       
   494      self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asInteger)    }
       
   495     "
       
   496 
       
   497     "Modified: / 19-06-2017 / 15:21:34 / cg"
       
   498 !
       
   499 
       
   500 printf:formatString on:outStream argument: arg
       
   501     "Format and print formatString on <outStream> with <arg>
       
   502      formatted in C style, as described in the UTek manual page for
       
   503      printf(3)."     
       
   504 
       
   505     ^ self printf:formatString on:outStream arguments:{ arg }
       
   506 
       
   507     "
       
   508      self printf:'%e' on:Transcript argument:(1.234 asShortFloat). Transcript cr.
       
   509      self printf:'%e' on:Transcript argument:(1.234 asFloat)     . Transcript cr.
       
   510      self printf:'%e' on:Transcript argument:(1.234 asLongFloat) . Transcript cr.
       
   511      self printf:'%e' on:Transcript argument:(1.234 asQDouble)   . Transcript cr.
       
   512      self printf:'%e' on:Transcript argument:(1.234 asInteger)   . Transcript cr.
       
   513 
       
   514      self printf:'%10e' on:Transcript argument:(1.234 asShortFloat). Transcript cr.
       
   515      self printf:'%10e' on:Transcript argument:(1.234 asFloat)     . Transcript cr.
       
   516      self printf:'%10e' on:Transcript argument:(1.234 asLongFloat) . Transcript cr.
       
   517      self printf:'%10e' on:Transcript argument:(1.234 asQDouble)   . Transcript cr.
       
   518      self printf:'%10e' on:Transcript argument:(1.234 asInteger)   . Transcript cr.
       
   519 
       
   520      self printf:'%010e' on:Transcript argument:(1.234 asInteger)  . Transcript cr.
       
   521      self printf:'%-10e' on:Transcript argument:(1.234 asInteger)  . Transcript cr.
       
   522 
       
   523      self printf:'%10.9f' on:Transcript argument:(1.2345 asShortFloat). Transcript cr.
       
   524      self printf:'%10.9f' on:Transcript argument:(1.2345 asFloat)     . Transcript cr.
       
   525      self printf:'%10.9f' on:Transcript argument:(1.2345 asLongFloat) . Transcript cr.
       
   526      self printf:'%10.9f' on:Transcript argument:(1.2345 asQDouble)   . Transcript cr.
       
   527      self printf:'%10.9f' on:Transcript argument:(1.2345 asInteger)   . Transcript cr.
       
   528     "
       
   529 
       
   530     "Created: / 16-06-2017 / 14:50:40 / cg"
       
   531     "Modified (comment): / 19-06-2017 / 15:07:22 / cg"
   589 !
   532 !
   590 
   533 
   591 printf:aFormatString on:outStream arguments: args
   534 printf:aFormatString on:outStream arguments: args
   592     "Format and print aFormatString on <outStream> with <args>
   535     "Format and print aFormatString on <outStream> with <args>
   593      formatted in C style, as described in the UTek manual page for
   536      formatted in C style, as described in the UTek manual page for
   594      printf(3).  
   537      printf(3)."     
   595      This method is designed for producing output suitable for a machine."     
       
   596 
   538 
   597     | argStream inStream char |
   539     | argStream inStream char |
   598 
   540 
   599     argStream := ReadStream on: args.
   541     argStream := ReadStream on: args.
   600     inStream := ReadStream on: aFormatString.
   542     inStream := ReadStream on: aFormatString.
   604         ] ifTrue: [
   546         ] ifTrue: [
   605             self printArgFrom:inStream to:outStream arguments:argStream
   547             self printArgFrom:inStream to:outStream arguments:argStream
   606         ]
   548         ]
   607     ]
   549     ]
   608 
   550 
   609     "Modified (comment): / 16-06-2017 / 15:09:10 / cg"
   551     "
       
   552      self printf:'%e' on:Transcript arguments:{ (1.234 asShortFloat) }
       
   553      self printf:'%e' on:Transcript arguments:{ (1.234 asFloat)      }
       
   554      self printf:'%e' on:Transcript arguments:{ (1.234 asLongFloat)  }
       
   555      self printf:'%e' on:Transcript arguments:{ (1.234 asQDouble)    }
       
   556      self printf:'%e' on:Transcript arguments:{ (1.234 asInteger)    }
       
   557 
       
   558      self printf:'%10e' on:Transcript arguments:{ (1.234 asShortFloat) }
       
   559      self printf:'%10e' on:Transcript arguments:{ (1.234 asFloat)      }
       
   560      self printf:'%10e' on:Transcript arguments:{ (1.234 asLongFloat)  }
       
   561      self printf:'%10e' on:Transcript arguments:{ (1.234 asQDouble)    }
       
   562      self printf:'%10e' on:Transcript arguments:{ (1.234 asInteger)    }
       
   563 
       
   564      self printf:'%010e' on:Transcript arguments:{ (1.234 asInteger)    }
       
   565      self printf:'%-10e' on:Transcript arguments:{ (1.234 asInteger)    }
       
   566 
       
   567      self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asShortFloat) }
       
   568      self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asFloat)      }
       
   569      self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asLongFloat)  }
       
   570      self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asQDouble)    }
       
   571      self printf:'%10.9f' on:Transcript arguments:{ (1.2345 asInteger)    }
       
   572     "
       
   573 
       
   574     "Modified: / 19-06-2017 / 15:21:07 / cg"
       
   575 ! !
       
   576 
       
   577 !PrintfScanf class methodsFor:'scanning'!
       
   578 
       
   579 scanf:formatString fromStream:dataStream 
       
   580     "Return a Collection of objects found in the Character Stream
       
   581      <dataStream> as interpreted according to the receiver.  The
       
   582      receiver is assumed to be a conversion control string as
       
   583      specified in the UTek manual page for scanf(3)."
       
   584 
       
   585    ^ self new scanf:formatString fromStream:dataStream
       
   586 !
       
   587 
       
   588 sscanf:formatString fromString:aString 
       
   589     "Return a Collection of objects found in <string> as
       
   590      interpreted according to the receiver.  The receiver is
       
   591      assumed to be a conversion control string as specified in the
       
   592      UTek manual page for scanf(3)."
       
   593 
       
   594    ^ self new sscanf:formatString fromString:aString
       
   595 ! !
       
   596 
       
   597 !PrintfScanf methodsFor:'helpers'!
       
   598 
       
   599 absDecimalPrintFloat:arg1 on:arg2 digits:arg3
       
   600     ^ self class absDecimalPrintFloat:arg1 on:arg2 digits:arg3
       
   601 !
       
   602 
       
   603 absPrintFloat:arg1 on:arg2 digits:arg3
       
   604     ^ self class absPrintFloat:arg1 on:arg2 digits:arg3
       
   605 !
       
   606 
       
   607 absScientificPrintFloat:arg1 on:arg2 digits:arg3
       
   608     ^ self class absScientificPrintFloat:arg1 on:arg2 digits:arg3
       
   609 !
       
   610 
       
   611 formatArgCountFor:arg
       
   612     ^ self class formatArgCountFor:arg
       
   613 ! !
       
   614 
       
   615 !PrintfScanf methodsFor:'printing'!
       
   616 
       
   617 printArgFrom:arg1 to:arg2 arguments:arg3
       
   618     ^ self class printArgFrom:arg1 to:arg2 arguments:arg3
       
   619 !
       
   620 
       
   621 printf:aString arguments:args 
       
   622     "Format and print the receiver with <args> formatted in C style, 
       
   623      as described in the UTek manual page for printf(3).
       
   624      Returns the formatted printString."
       
   625     
       
   626     ^ self class printf:aString arguments:args
       
   627 
       
   628     "
       
   629      self new printf:'%d %x' arguments:#(1234 45054) 
       
   630     "
       
   631 
       
   632     "Modified: / 19-06-2017 / 15:21:56 / cg"
       
   633 !
       
   634 
       
   635 printf:aFormatString on:outStream arguments: args
       
   636     "Format and print aFormatString on <outStream> with <args>
       
   637      formatted in C style, as described in the UTek manual page for
       
   638      printf(3)."     
       
   639 
       
   640     self class printf:aFormatString on:outStream arguments: args
       
   641 
       
   642     "Modified (comment): / 19-06-2017 / 15:22:15 / cg"
   610 ! !
   643 ! !
   611 
   644 
   612 !PrintfScanf methodsFor:'scanning'!
   645 !PrintfScanf methodsFor:'scanning'!
   613 
   646 
   614 scanArgFrom:dataStream to:collection format:format 
   647 scanArgFrom:dataStream to:collection format:format 
   738         (char == Character space or:[ char == Character tab ]) ifTrue:[
   771         (char == Character space or:[ char == Character tab ]) ifTrue:[
   739             dataStream skipSeparators.
   772             dataStream skipSeparators.
   740             format skipSeparators
   773             format skipSeparators
   741         ].
   774         ].
   742         char == $% ifTrue:[
   775         char == $% ifTrue:[
   743             self 
   776             self scanArgFrom:dataStream to:results format:format
   744                 scanArgFrom:dataStream
       
   745                 to:results
       
   746                 format:format
       
   747         ] ifFalse:[
   777         ] ifFalse:[
   748             dataStream peekFor:char
   778             dataStream peekFor:char
   749         ]
   779         ]
   750     ].
   780     ].
   751     ^ results
   781     ^ results
       
   782 
       
   783     "Modified (format): / 19-06-2017 / 15:22:46 / cg"
   752 !
   784 !
   753 
   785 
   754 sscanf:formatString fromString:aString 
   786 sscanf:formatString fromString:aString 
   755     "Return a Collection of objects found in <string> as
   787     "Return a Collection of objects found in <string> as
   756      interpreted according to the receiver.  The receiver is
   788      interpreted according to the receiver.  The receiver is