Index: trunk/Include/Classes/ActiveBasic/Strings/SPrintF.ab
===================================================================
--- trunk/Include/Classes/ActiveBasic/Strings/SPrintF.ab	(revision 382)
+++ trunk/Include/Classes/ActiveBasic/Strings/SPrintF.ab	(revision 383)
@@ -102,4 +102,7 @@
 	Cap = &h20
 
+	'!BASIC接頭辞。&h, &oなど。
+	BPrefix = &h40
+
 	/*!
 	内部処理用に予約。
@@ -114,5 +117,5 @@
 @date	2007/09/18
 @param[in] x	文字列化する浮動小数点数値。
-@param[in] d	精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値6となる。
+@param[in] precision	精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値6となる。
 @param[in] field	フィールド幅。
 @param[in] flags	書式フラグ。
@@ -121,30 +124,49 @@
 @todo	他の実装での末尾桁の扱いを調べる（このコードでは何もしていないので切捨となっている）。
 */
-Function FormatFloatE(x As Double, d As DWord, field As DWord, flags As FormatFlags) As String
-	If d = DWORD_MAX Then
-		d = 6
+Function FormatFloatE(x As Double, precision As DWord, field As DWord, flags As FormatFlags) As String
+	If precision = DWORD_MAX Then
+		precision = 6
 	End If
 
 	Dim e As Long, negative As Boolean
 	Dim s = FloatToChars(x, e, negative)
-
-	Dim sb = New System.Text.StringBuilder
-	With sb
-
-		AppendSign(sb, negative, flags)
+	Dim sb = FormatFloatE_Base(s, negative, precision, flags)
+	FormatFloatE_Exponent(sb, e, flags)
+	AdjustFieldWidth(sb, field, flags)
+	FormatFloatE = sb.ToString()
+End Function
+
+/**
+@brief	FormatFloatEの符号・基数部の出力用。
+@author	Egtra
+@date	2007/10/27
+*/
+Function FormatFloatE_Base(s As String, negative As Boolean, precision As DWord, ByRef flags As FormatFlags) As System.Text.StringBuilder
+	FormatFloatE_Base = New System.Text.StringBuilder
+	With FormatFloatE_Base
+		AppendSign(FormatFloatE_Base, negative, flags)
 
 		.Append(s[0])
 
-		If (flags And Alt) Or d > 0 Then
+		If (flags And Alt) Or precision > 0 Then
 			.Append(".")
 			Dim outputLen = s.Length - 1
-			If outputLen >= d Then
-				.Append(s, 1, d)
+			If outputLen >= precision Then
+				.Append(s, 1, precision)
 			Else 'sで用意された桁が指定された精度より少ないとき
 				.Append(s, 1, outputLen)
-				.Append(&h30 As StrChar, d - outputLen) '足りない桁は0埋め
+				.Append(&h30 As StrChar, precision - outputLen) '足りない桁は0埋め
 			End If
 		End If
-
+	End With
+End Function
+
+/**
+@brief	FormatFloatEの指数部の出力用。
+@author	Egtra
+@date	2007/10/27
+*/
+Sub FormatFloatE_Exponent(buf As System.Text.StringBuilder, e As Long, flags As FormatFlags)
+	With buf
 		If flags And Cap Then
 			.Append("E")
@@ -152,11 +174,7 @@
 			.Append("e")
 		End If
-
 		.Append(FormatIntegerD(e, 2, 0, Sign Or Zero))
-
-		AdjustFieldWidth(sb, field, flags)
 	End With
-	FormatFloatE = sb.ToString()
-End Function
+End Sub
 
 /*!
@@ -177,8 +195,17 @@
 	Dim e As Long, negative As Boolean
 	Dim s = FloatToChars(x, e, negative)
-
-	Dim sb = New System.Text.StringBuilder
-	With sb
-		AppendSign(sb, negative, flags)
+	Dim sb = FormatFloatF_Core(s, e, negative, precision, flags)
+	AdjustFieldWidth(sb, field, flags)
+	FormatFloatF = sb.ToString()
+End Function
+
+/**
+@author	Egtra
+@date	2007/10/27
+*/
+Function FormatFloatF_Core(s As String, e As Long, negative As Boolean, precision As DWord, ByRef flags As FormatFlags) As System.Text.StringBuilder
+	FormatFloatF_Core = New System.Text.StringBuilder
+	With FormatFloatF_Core
+		AppendSign(FormatFloatF_Core, negative, flags)
 
 		Dim intPartLen = e + 1
@@ -215,7 +242,144 @@
 			End If
 		End If
-		AdjustFieldWidth(sb, field, flags)
 	End With
-	FormatFloatF = sb.ToString()
+End Function
+
+/*!
+@brief	浮動小数点数をprintfの%g, %G（小数・指数、十進法）相当の変換で文字列化する関数。
+@author	Egtra
+@date	2007/10/23
+@param[in]	x	文字列化する浮動小数点数値。
+@param[in]	precision	精度。小数点以下の桁数。DWORD_MAXまたは0のとき、指定なしとして既定値6となる。
+@param[in]	field	フィールド幅。
+@param[in]	flags	書式フラグ。
+@return xの文字列表現
+@todo	下位桁の扱いの調査。
+*/
+Function FormatFloatG(x As Double, precision As DWord, field As DWord, flags As FormatFlags) As String
+	'GではE/Fと違い整数部も有効桁数に数えるのでその分を引いておく。
+	If precision = DWORD_MAX Or precision = 0 Then
+		precision = 5
+	Else
+		precision--
+	End If
+
+	Dim e As Long, negative As Boolean
+	Dim s = FloatToChars(x, e, negative)
+
+	Dim sb = Nothing As System.Text.StringBuilder
+
+	If -5 < e And e < precision Then
+		sb = FormatFloatF_Core(s, e, negative, -e + precision, flags)
+		FormatFloatG_RemoveLowDigit(sb, flags)
+	Else
+		sb = FormatFloatE_Base(s, negative, precision, flags)
+		FormatFloatG_RemoveLowDigit(sb, flags)
+		FormatFloatE_Exponent(sb, e, flags)
+	End If
+
+	AdjustFieldWidth(sb, field, flags)
+	FormatFloatG = sb.ToString()
+End Function
+
+/*!
+@brief	FormatFloatG/A用の小数点以下末尾の0を削除するルーチン
+@author	Egtra
+@date	2007/10/27
+@param[in, out]	sb 文字列バッファ
+@param[in]	flags フラグ
+flagsでAltが立っているとき、この関数は何もしない。
+*/
+Sub FormatFloatG_RemoveLowDigit(sb As System.Text.StringBuilder, flags As FormatFlags)
+	Imports ActiveBasic.Strings
+	
+	Dim count = sb.Length
+	If (flags And Alt) = 0 Then
+		Dim point = ChrFind(StrPtr(sb), count As SIZE_T, Asc("."))
+		If point = -1 Then
+			Debug
+		End If
+
+		Dim i As Long
+		For i = count - 1 To point + 1 Step -1
+			If sb[i] <> &h30 Then
+				Exit For
+			End If
+		Next
+		If i <> point Then
+			i++
+		End If
+		sb.Length = i
+	End If
+End Sub
+
+/*!
+@brief	浮動小数点数をprintfの%a, %A（指数形式、十六進法）相当の変換で文字列化する関数。
+@author	Egtra
+@date	2007/09/18
+@param[in] x	文字列化する浮動小数点数値。
+@param[in] precision	精度。小数点以下の桁数。DWORD_MAXのとき、指定なしとして既定値13となる。
+@param[in] field	フィールド幅。
+@param[in] flags	書式フラグ。
+@return	xの文字列表現
+
+C99では、末尾の0を取り除いても良いとあるので、
+このルーチンでは取り除くことにしている。
+*/
+Function FormatFloatA(x As Double, precision As DWord, field As DWord, flags As FormatFlags) As String
+	If precision = DWORD_MAX Then
+		precision = 13
+	End If
+
+	Dim pqw = VarPtr(x) As *QWord
+
+	Dim sb = New System.Text.StringBuilder
+	With sb
+		Dim sign = (GetQWord(pqw) And &H8000000000000000) As Boolean
+		pqw[0] And= &h7fffffffffffffff
+
+		AppendSign(sb, sign, flags)
+
+		If flags And BPrefix Then
+			.Append("&H")
+		Else
+			.Append("0X")
+		End If
+
+		Dim biasedExp = (GetQWord(pqw) >> 52) As DWord And &h7FF
+		Dim exp As Long
+		If biasedExp = 0 Then
+			If GetQWord(pqw) <> 0 Then
+				exp = -1022 '非正規化数への対応
+			Else
+				exp = 0
+			End If
+			.Append("0")
+		Else
+			exp = biasedExp - 1023
+			.Append("1")
+		End If
+
+		If precision > 0 Or (flags And Alt) Then
+			.Append(".")
+			Dim base = FormatIntegerLX(GetQWord(pqw) And &h000fffffffffffff, 13, 0, flags And Cap)
+			Dim diff = precision - 13 As Long
+			If diff <= 0 Then
+				.Append(Left$(base, precision))
+			Else
+				.Append(base).Append(&h30, diff)
+			End If
+		End If
+
+		FormatFloatG_RemoveLowDigit(sb, flags)
+
+		.Append("P")
+		.Append(FormatIntegerD(exp, 1, 0, Sign))
+		
+		FormatFloatA = .ToString()
+	End With
+
+	If (flags And Cap) = 0 Then
+		FormatFloatA = FormatFloatA.ToLower()
+	End If
 End Function
 
@@ -261,5 +425,5 @@
 */
 Function FormatIntegerU(x As DWord, d As DWord, field As DWord, flags As FormatFlags) As String
-	Return FormatIntegerEx(TraitsIntegerDU, x, d, field, flags And (Not (Sign Or Blank)))
+	Return FormatIntegerEx(TraitsIntegerU[0], x, d, field, flags And (Not (Sign Or Blank)))
 End Function
 
@@ -270,5 +434,5 @@
 */
 Function FormatIntegerLU(x As QWord, d As DWord, field As DWord, flags As FormatFlags) As String
-	Return FormatIntegerEx(TraitsIntegerLDU, x, d, field, flags And (Not (Sign Or Blank)))
+	Return FormatIntegerEx(TraitsIntegerU[1], x, d, field, flags And (Not (Sign Or Blank)))
 End Function
 
@@ -284,13 +448,5 @@
 */
 Function FormatIntegerD(x As Long, d As DWord, field As DWord, flags As FormatFlags) As String
-	Dim unsignedX As DWord
-	If x < 0 Then
-		unsignedX = (-x) As DWord
-		flags Or= Minus
-	Else
-		unsignedX = x As DWord
-	End If
-
-	Return FormatIntegerEx(TraitsIntegerDU, unsignedX, d, field, flags)
+	Return FormatIntegerEx(TraitsIntegerD[0], (x As Int64) As QWord, d, field, flags)
 End Function
 
@@ -301,13 +457,5 @@
 */
 Function FormatIntegerLD(x As Int64, d As DWord, field As DWord, flags As FormatFlags) As String
-	Dim unsignedX As QWord
-	If x < 0 Then
-		unsignedX = (-x) As QWord
-		flags Or= Minus
-	Else
-		unsignedX = x As QWord
-	End If
-
-	Return FormatIntegerEx(TraitsIntegerLDU, unsignedX, d, field, flags)
+	Return FormatIntegerEx(TraitsIntegerD[1], x As QWord, d, field, flags)
 End Function
 
@@ -316,23 +464,35 @@
 @date	2007/10/26
 */
-Dim TraitsIntegerDU As IntegerConvertTraits
-With TraitsIntegerDU
-	.Convert = AddressOf(IntegerDU_Convert)
-	.Prefix = AddressOf(IntegerDU_Prefix)
+Dim TraitsIntegerU[1] As IntegerConvertTraits
+With TraitsIntegerU[0]
+	.Convert = AddressOf(IntegerU_Convert)
+	.Prefix = AddressOf(IntegerU_Prefix)
 	.MaxSize = MaxSizeU
 End With
 
-/*!
-@author	Egtra
-@date	2007/10/26
-*/
-Dim TraitsIntegerLDU As IntegerConvertTraits
-With TraitsIntegerLDU
-	.Convert = AddressOf(IntegerLDU_Convert)
-	.Prefix = AddressOf(IntegerDU_Prefix)
+With TraitsIntegerU[1]
+	.Convert = AddressOf(IntegerLU_Convert)
+	.Prefix = AddressOf(IntegerU_Prefix)
 	.MaxSize = MaxSizeLU
 End With
 
 /*!
+@author	Egtra
+@date	2007/10/28
+*/
+Dim TraitsIntegerD[1] As IntegerConvertTraits
+With TraitsIntegerD[0]
+	.Convert = AddressOf(IntegerD_Convert)
+	.Prefix = AddressOf(IntegerD_Prefix)
+	.MaxSize = MaxSizeU
+End With
+
+With TraitsIntegerD[1]
+	.Convert = AddressOf(IntegerLD_Convert)
+	.Prefix = AddressOf(IntegerD_Prefix)
+	.MaxSize = MaxSizeLU
+End With
+
+/*!
 @brief	負数を表すフラグ。FormatIntegerD, LDからIntegerDU_Prefixまでの内部処理用。
 @author	Egtra
@@ -345,5 +505,5 @@
 @date	2007/10/26
 */
-Function IntegerDU_Convert(buf As *StrChar, xq As QWord, flags As FormatFlags) As DWord
+Function IntegerU_Convert(buf As *StrChar, xq As QWord, flags As FormatFlags) As DWord
 	Dim x = xq As DWord
 	Dim i = MaxSizeU
@@ -357,10 +517,10 @@
 
 /*!
-@brief	IntegerDU_ConvertのQWord版
+@brief	IntegerU_ConvertのQWord版
 @author	Egtra
 @date	2007/10/26
 @bug	#117のため、現在Int64の最大値を超える値を正しく処理できない。
 */
-Function IntegerLDU_Convert(buf As *StrChar, x As QWord, flags As FormatFlags) As DWord
+Function IntegerLU_Convert(buf As *StrChar, x As QWord, flags As FormatFlags) As DWord
 	Dim i = MaxSizeLU
 	While x <> 0
@@ -376,11 +536,35 @@
 @date	2007/10/26
 */
-Function IntegerDU_Prefix(x As QWord, flags As FormatFlags) As String
-	If flags And Minus Then
-		IntegerDU_Prefix = "-"
+Function IntegerU_Prefix(x As QWord, flags As FormatFlags) As String
+End Function
+
+/*!
+@author	Egtra
+@date	2007/10/28
+*/
+Function IntegerD_Convert(buf As *StrChar, xq As QWord, flags As FormatFlags) As DWord
+	Return IntegerU_Convert(buf, Abs((xq As DWord) As Long) As DWord, flags)
+End Function
+
+/*!
+@brief	IntegerD_ConvertのInt64版
+@author	Egtra
+@date	2007/10/28
+*/
+Function IntegerLD_Convert(buf As *StrChar, x As QWord, flags As FormatFlags) As DWord
+	Return IntegerLU_Convert(buf, Abs(x As Int64) As QWord, flags)
+End Function
+
+/*!
+@author	Egtra
+@date	2007/10/28
+*/
+Function IntegerD_Prefix(x As QWord, flags As FormatFlags) As String
+	If (x As Int64) < 0 Then
+		IntegerD_Prefix = "-"
 	ElseIf flags And Sign Then
-		IntegerDU_Prefix = "+"
+		IntegerD_Prefix = "+"
 	ElseIf flags And Blank Then
-		IntegerDU_Prefix = " "
+		IntegerD_Prefix = " "
 	End If
 End Function
@@ -406,6 +590,6 @@
 @date	2007/10/22
 */
-Dim TraitsIntegerO As IntegerConvertTraits
-With TraitsIntegerO
+Dim TraitsIntegerO[1] As IntegerConvertTraits
+With TraitsIntegerO[0]
 	.Convert = AddressOf(IntegerO_Convert)
 	.Prefix = AddressOf(IntegerO_Prefix)
@@ -413,10 +597,5 @@
 End With
 
-/*!
-@author	Egtra
-@date	2007/10/26
-*/
-Dim TraitsIntegerLO As IntegerConvertTraits
-With TraitsIntegerLO
+With TraitsIntegerO[1]
 	.Convert = AddressOf(IntegerLO_Convert)
 	.Prefix = AddressOf(IntegerO_Prefix)
@@ -435,5 +614,5 @@
 */
 Function FormatIntegerO(x As DWord, d As DWord, field As DWord, flags As FormatFlags) As String
-	Return FormatIntegerEx(TraitsIntegerO, x, d, field, flags)
+	Return FormatIntegerEx(TraitsIntegerO[0], x, d, field, flags)
 End Function
 
@@ -444,5 +623,5 @@
 */
 Function FormatIntegerLO(x As QWord, d As DWord, field As DWord, flags As FormatFlags) As String
-	Return FormatIntegerEx(TraitsIntegerLO, x, d, field, flags)
+	Return FormatIntegerEx(TraitsIntegerO[1], x, d, field, flags)
 End Function
 
@@ -491,4 +670,9 @@
 */
 Function IntegerO_Prefix(x As QWord, flags As FormatFlags) As String
+	If flags And BPrefix Then
+		If x <> 0 Then
+			IntegerO_Prefix = "&O"
+		End If
+	End If
 End Function
 
@@ -511,6 +695,6 @@
 @date	2007/10/24
 */
-Dim TraitsIntegerX As IntegerConvertTraits
-With TraitsIntegerX
+Dim TraitsIntegerX[1] As IntegerConvertTraits
+With TraitsIntegerX[0]
 	.Convert = AddressOf(IntegerX_Convert)
 	.Prefix = AddressOf(IntegerX_Prefix)
@@ -518,10 +702,5 @@
 End With
 
-/*!
-@author	Egtra
-@date	2007/10/26
-*/
-Dim TraitsIntegerLX As IntegerConvertTraits
-With TraitsIntegerLX
+With TraitsIntegerX[1]
 	.Convert = AddressOf(IntegerLX_Convert)
 	.Prefix = AddressOf(IntegerX_Prefix)
@@ -540,5 +719,5 @@
 */
 Function FormatIntegerX(x As DWord, d As DWord, field As DWord, flags As FormatFlags) As String
-	Return FormatIntegerEx(TraitsIntegerX, x, d, field, flags)
+	Return FormatIntegerEx(TraitsIntegerX[0], x, d, field, flags)
 End Function
 
@@ -549,5 +728,5 @@
 */
 Function FormatIntegerLX(x As QWord, d As DWord, field As DWord, flags As FormatFlags) As String
-	Return FormatIntegerEx(TraitsIntegerLX, x, d, field, flags)
+	Return FormatIntegerEx(TraitsIntegerX[1], x, d, field, flags)
 End Function
 
@@ -587,7 +766,9 @@
 */
 Function IntegerX_Prefix(x As QWord, flags As FormatFlags) As String
-	If flags And Alt Then
-		If x <> 0 Then
+	If x <> 0 Then
+		If flags And Alt Then
 			IntegerX_Prefix = "0X"
+		ElseIf flags And BPrefix Then
+			IntegerX_Prefix = "&H"
 		End If
 	End If
@@ -598,4 +779,7 @@
 @author	Egtra
 @date	2007/10/22
+
+FormatIntegerの都合上、このファイル内で宣言しているIntegerConvertTraits型の
+変数は全て配列となっている；[0]が32ビット変換、[1]が64ビット変換である。
 */
 Type IntegerConvertTraits
@@ -701,5 +885,595 @@
 End Sub
 
+/*!
+@brief	文字列をprintfの%s相当の変換で書式化する関数。
+@author	Egtra
+@date	2007/10/27
+@param[in]	x	文字列。
+@param[in]	d	精度、最大の文字数。
+@param[in]	field	フィールド幅。
+@param[in]	flags	書式フラグ。
+@return 書式化された文字列。
+*/
+Function FormatString(x As String, d As DWord, field As DWord, flags As FormatFlags) As String
+	Dim sb = New System.Text.StringBuilder(
+		x, 0, System.Math.Min(x.Length As DWord, d) As Long, field)
+	AdjustFieldWidth(sb, field, flags And Left)
+	FormatString = sb.ToString()
+End Function
+
+/*!
+@brief	文字をprintfの%c相当の変換で書式化する関数。
+@author	Egtra
+@date	2007/10/27
+@param[in]	x	文字。
+@param[in]	d	精度、最大の文字数。
+@param[in]	field	フィールド幅。
+@param[in]	flags	書式フラグ。
+@return 書式化された文字列。
+*/
+Function FormatCharacter(x As StrChar, d As DWord, field As DWord, flags As FormatFlags) As String
+	Dim sb = New System.Text.StringBuilder(field + 1)
+	sb.Append(x)
+	AdjustFieldWidth(sb, field, flags And Left)
+	FormatCharacter = sb.ToString()
+End Function
+
+/*!
+@author	Egtra
+@date	2007/10/28
+*/
+TypeDef FormatFloatProc = *Function(x As Double, precision As DWord, fieldWidth As DWord, flags As FormatFlags) As String
+
+/*!
+@author	Egtra
+@date	2007/10/28
+*/
+Sub FormatFloat(s As System.Text.StringBuilder, formatProc As FormatFloatProc,
+	param As Object, precision As DWord, field As DWord, flags As FormatFlags)
+
+	Dim x As Double
+	Dim typeName = param.GetType().FullName
+	If typeName = "System.Double" Then
+		x = param As System.Double
+	ElseIf typeName = "System.Single" Then
+		x = param As System.Single
+	End If
+	s.Append(formatProc(x, precision, field, flags))
+End Sub
+
+/*!
+@author	Egtra
+@date	2007/10/28
+*/
+Sub FormatInteger(s As System.Text.StringBuilder, traits As *IntegerConvertTraits,
+	param As Object, signed As Boolean, typeWidth As Long, precision As DWord, field As DWord, flags As FormatFlags)
+
+	Dim x As QWord
+	Dim typeName = param.GetType().FullName
+	If typeName = "System.UInt64" Then
+		x = param As System.UInt64
+	ElseIf typeName = "System.Int64" Then
+		x = (param As System.Int64) As QWord
+	ElseIf typeName = "System.UInt32" Then
+		x = param As System.UInt32
+	ElseIf typeName = "System.Int32" Then
+		x = (param As System.Int32) As QWord
+	ElseIf typeName = "System.UInt16" Then
+		x = param As System.UInt16
+	ElseIf typeName = "System.Int16" Then
+		x = (param As System.Int16) As QWord
+	ElseIf typeName = "System.UInt8" Then
+		x = param As System.Byte
+	ElseIf typeName = "System.Int8" Then
+		x = (param As System.SByte) As QWord
+	End If
+	'一旦縮めた後、符号・ゼロ拡張させる。
+	'また、64ビット整数なら64ビット変換Traitsを選択する。
+	If signed Then
+		If typeWidth = 1 Then
+			traits = VarPtr(traits[1])
+		ElseIf typeWidth = 0 Then
+			x = (((x As DWord) As Long) As Int64) As QWord
+		ElseIf typeWidth = -1 Then
+			x = (((x As Word) As Integer) As Int64) As QWord
+		ElseIf typeWidth = -2 Then
+			x = (((x As Byte) As SByte) As Int64) As QWord
+		End If
+	Else
+		If typeWidth = 1 Then
+			traits = VarPtr(traits[1])
+		ElseIf typeWidth = 0 Then
+			x = x As DWord
+		ElseIf typeWidth = -1 Then
+			x = x As Word
+		ElseIf typeWidth = -2 Then
+			x = x As Byte
+		End If
+	End If
+
+	s.Append(FormatIntegerEx(ByVal traits, x, precision, field, flags))
+End Sub
+
+'Format関数群ここまで
+'----
+
+/*!
+@brief	文字列から数値への変換。さらに変換に使われなかった文字列の位置を返す。
+@author	Egtra
+@date	2007/11/11
+@param[in] s	変換する文字
+@param[out] p	変換に使われなかった部分の先頭を指すポインタ
+@return	変換して得られた数値。変換できなければ0。
+*/
+Function StrToLong(s As *StrChar, ByRef p As *StrChar) As Long
+	Dim negative As Boolean
+	Dim i = 0 As Long
+	If s[i] = &h2d Then 'Asc("-")
+		i++
+		negative = True
+	End If
+	Do
+		Dim c = s[i]
+		If Not IsDigit(c) Then Exit Do
+		StrToLong *= 10
+		StrToLong += ((c As DWord) And &h0f) As Long
+		i++
+	Loop
+	If negative Then
+		StrToLong = -StrToLong
+	End If
+	p = VarPtr(s[i])
+End Function
+
+/*!
+@brief	文字が十進数字かどうか調べる。
+@author	Egtra
+@date	2007/11/11
+@param[in] c	調べる文字
+@retval True	0から9の文字である
+@retval False	そうでない
+*/
+Function IsDigit(c As StrChar) As Boolean
+	Dim dw = (c As DWord)
+	IsDigit = (dw - &h30) < 10
+End Function
+
+/*!
+@brief	フィールド幅、精度用の数値読取
+@author	Egtra
+@date	2007/11/11
+@param[in, out] fmt	読み途中の書式指定
+@param[in] params
+@param[in, out] paramsCount
+@param[out]	ret	読み取った数値。読み取られなかったときの値は不定。
+@retval True	読取を行った
+@retval False	行わなかった
+fmt[0]が*のときにはparamsから1つ読み取る。
+そうでなく、fmtに数字（先頭に-符号があっても可）が並んでいれば、それを読み取る。
+*/
+Function ReadInt(ByRef fmt As *StrChar, params As *Object, ByRef paramsCount As SIZE_T, ByRef ret As Long) As Boolean
+	If fmt[0] = &h2a Then '*
+		fmt++ 'p
+		ret = params[paramsCount] As System.Int32
+		paramsCount++
+		ReadInt = True
+	Else
+		Dim p As PSTR
+		ret = StrToLong(fmt, p)
+		If fmt <> p Then
+			fmt = p
+			ReadInt = True
+		Else
+			ReadInt = False
+		End If
+	End If
+End Function
+
+/*!
+@brief	フラグ指定の読み込み
+@author	Egtra
+@date	2007/10/28
+@param[in, out] fmt
+@param[out] flags
+@retval True	読み込みが完了した。
+@retval False	読み取り中に文字列が終了した（ヌル文字が現れた）。
+*/
+Function ReadFlags(ByRef fmt As *StrChar, ByRef flags As FormatFlags) As Boolean
+	ReadFlags = False
+	Do
+		Select Case fmt[0]
+			Case &h23 '#
+				flags Or= Alt
+			Case &h30 '0
+				flags Or= Zero
+			Case &h20 '空白
+				flags Or= Blank
+			Case &h2b '+
+				flags Or= Sign
+			Case &h2d '-
+				flags Or = Left
+			Case &h26 '&
+				flags Or= BPrefix
+			Case 0
+				Exit Function
+			Case Else
+				Exit Do
+		End Select
+		fmt++ 'p
+	Loop
+	ReadFlags = True
+End Function
+
+/*!
+@brief	フィールド幅指定の読み込み
+@author	Egtra
+@date	2007/10/29
+@param[in, out] fmt
+@param[in] params
+@param[in, out] paramsCount
+@param[out] fieldWidth
+@param[in, out] flags
+*/
+Sub ReadFieldWidth(ByRef fmt As *StrChar, params As *Object, ByRef paramsCount As SIZE_T,
+	ByRef fieldWidth As DWord, ByRef flags As FormatFlags)
+	Dim t As Long
+	If ReadInt(fmt, params, paramsCount, t) Then
+		If t < 0 Then
+			flags Or= Left
+			fieldWidth = -t As DWord
+		Else
+			fieldWidth = t As DWord
+		End If
+	Else
+		fieldWidth = 0
+	End If
+End Sub
+
+/*!
+@brief	精度の読み込み
+@author	Egtra
+@date	2007/10/29
+@param[in, out] fmt
+@param[in] params
+@param[in, out] paramsCount
+@return	読み取った精度。指定がなかったときには、DWORD_MAX。
+*/
+Function ReadPrecision(ByRef fmt As *StrChar,
+	params As *Object, ByRef paramsCount As SIZE_T) As DWord
+
+	If fmt[0] = &h2e Then '.
+		fmt++
+		Dim t As Long
+		ReadPrecision = 0
+		If ReadInt(fmt, params, paramsCount, t) Then
+			If t > 0 Then
+				ReadPrecision = t As DWord
+			End If
+		End If
+	Else
+		ReadPrecision = DWORD_MAX
+	End If
+End Function
+
+/*!
+@biref	長さ指定の読み込み
+@author	Egtra
+@date	2007/10/29
+@param[in, out] fmt
+@param[out] lengthSpec
+*/
+Sub ReadLength(ByRef fmt As *StrChar, ByRef lengthSpec As Long)
+	Do
+		Select Case fmt[0]
+			Case &h6c 'l
+				lengthSpec++
+			Case &h68 'h
+				lengthSpec--
+			Case &h6a 'j (u)intmax_t
+				lengthSpec = 1
+#ifdef _WIN64
+			Case &h74 't ptrdiff_t
+				lengthSpec = 1
+			Case &h7a 'z (s)size_t,
+				lengthSpec = 1
+#else
+			Case &h74 't ptrdiff_t
+				lengthSpec = 0
+			Case &h7a 'z (s)size_t,
+				lengthSpec = 0
+#endif
+			Case Else
+				Exit Sub
+		End Select
+		fmt++ 'p
+	Loop
+End Sub
+
+/*!
+@author	Egtra
+@date	2007/10/27
+@todo	%nへの対応
+*/
+Function SPrintf(format As String, params As *Object, n As SIZE_T) As String
+	Dim i = 0 As DWord
+	Dim paramsCount = 0 As SIZE_T
+	Dim fmt = StrPtr(format)
+	Dim s = New System.Text.StringBuilder
+	Do
+		Dim last = format.Length - (fmt - StrPtr(format)) As Long 'p
+		Dim pos = ActiveBasic.Strings.ChrFind(fmt, last, &h25 As StrChar) '&h25 = %
+		If pos = -1 Then
+			s.Append(fmt, 0, last)
+			Exit Do
+		End If
+		'%以前の部分
+		s.Append(fmt, 0, pos)
+		fmt += pos + 1 'p
+		'フラグの読取
+		Dim flags = None As FormatFlags
+		If ReadFlags(fmt, flags) = False Then
+			Exit Do
+		End If
+		'フィールド幅
+		Dim fieldWidth As DWord
+		ReadFieldWidth(fmt, params, i, fieldWidth, flags)
+		'精度
+		Dim precision = ReadPrecision(fmt, params, i)
+		'幅指定の読取
+		Dim typeWidth As Long
+		ReadLength(fmt, typeWidth)
+
+		Select Case fmt[0]
+			Case &h64 'd
+				FormatInteger(s, TraitsIntegerD, params[i], True, typeWidth, precision, fieldWidth, flags)
+			Case &h69 'i
+				FormatInteger(s, TraitsIntegerD, params[i], True, typeWidth, precision, fieldWidth, flags)
+			Case &h75 'u
+				FormatInteger(s, TraitsIntegerU, params[i], False, typeWidth, precision, fieldWidth, flags)
+			Case &h6f 'o
+				FormatInteger(s, TraitsIntegerO, params[i], False, typeWidth, precision, fieldWidth, flags)
+			Case &h4f 'O
+				FormatInteger(s, TraitsIntegerO, params[i], False, typeWidth, precision, fieldWidth, flags Or Cap)
+			Case &h78 'x
+				FormatInteger(s, TraitsIntegerX, params[i], False, typeWidth, precision, fieldWidth, flags)
+			Case &h58 'X
+				FormatInteger(s, TraitsIntegerX, params[i], False, typeWidth, precision, fieldWidth, flags Or Cap)
+			Case &h65 'e
+				FormatFloat(s, AddressOf(FormatFloatE), params[i], precision, fieldWidth, flags)
+			Case &h45 'E
+				FormatFloat(s, AddressOf(FormatFloatE), params[i], precision, fieldWidth, flags Or Cap)
+			Case &h66 'f
+				FormatFloat(s, AddressOf(FormatFloatF), params[i], precision, fieldWidth, flags)
+			Case &h46 'F
+				FormatFloat(s, AddressOf(FormatFloatF), params[i], precision, fieldWidth, flags Or Cap)
+			Case &h67 'g
+				FormatFloat(s, AddressOf(FormatFloatG), params[i], precision, fieldWidth, flags)
+			Case &h47 'G
+				FormatFloat(s, AddressOf(FormatFloatG), params[i], precision, fieldWidth, flags Or Cap)
+			Case &h61 'a
+				FormatFloat(s, AddressOf(FormatFloatA), params[i], precision, fieldWidth, flags)
+			Case &h41 'A
+				FormatFloat(s, AddressOf(FormatFloatA), params[i], precision, fieldWidth, flags Or Cap)
+			Case &h73 's
+				s.Append(FormatString(params[i] As String, precision, fieldWidth, flags))
+			Case &h63 'c
+				s.Append(FormatCharacter(params[i] As BoxedStrChar, precision, fieldWidth, flags))
+'			Case &h6e 'n
+			Case &h25 '%
+				s.Append(&h25 As StrChar)
+				i--
+			Case 0
+				Exit Do
+		End Select
+		fmt++ 'p
+		i++
+	Loop
+	SPrintf = s.ToString
+End Function
+
 End Namespace 'Detail
+
+/*!
+@brief	Cのsprintfのような書式化関数10引数版
+@author	Egtra
+@date	2007/10/27
+@param[in] format	書式指定
+@param[in] paramN	引数
+@return 書式化された文字列
+*/
+
+Function SPrintf(format As String, param0 As Object,
+	param1 As Object, param2 As Object, param3 As Object,
+	param4 As Object, param5 As Object, param6 As Object,
+	param7 As Object, param8 As Object, param9 As Object) As String
+#ifdef _WIN64
+	'コンパイラがどういうコードを吐くのかわからないので、安全策を取る。
+	Dim params[9] = [param0, param1, param2, param3, param4,
+		param5, param6, param7, param8, param9] As Object
+#else
+	Dim params = VarPtr(param0) As *Object
+#endif
+	SPrintf = ActiveBasic.Strings.Detail.SPrintf(format, params, 10)
+End Function
+
+/*!
+@brief	Cのsprintfのような書式化関数9引数版
+@author	Egtra
+@date	2007/10/27
+@param[in] format	書式指定
+@param[in] paramN	引数
+@return 書式化された文字列
+*/
+Function SPrintf(format As String, param0 As Object,
+	param1 As Object, param2 As Object, param3 As Object,
+	param4 As Object, param5 As Object, param6 As Object,
+	param7 As Object, param8 As Object) As String
+#ifdef _WIN64
+	Dim params[8] = [param0, param1, param2, param3, param4,
+		param5, param6, param7, param8] As Object
+#else
+	Dim params = VarPtr(param0) As *Object
+#endif
+	SPrintf = ActiveBasic.Strings.Detail.SPrintf(format, params, 9)
+End Function
+
+/*!
+@brief	Cのsprintfのような書式化関数8引数版
+@author	Egtra
+@date	2007/10/27
+@param[in] format	書式指定
+@param[in] paramN	引数
+@return 書式化された文字列
+*/
+Function SPrintf(format As String, param0 As Object,
+	param1 As Object, param2 As Object, param3 As Object,
+	param4 As Object, param5 As Object, param6 As Object,
+	param7 As Object) As String
+#ifdef _WIN64
+	Dim params[7] = [param0, param1, param2, param3, param4,
+		param5, param6, param7] As Object
+#else
+	Dim params = VarPtr(param0) As *Object
+#endif
+	SPrintf = ActiveBasic.Strings.Detail.SPrintf(format, params, 8)
+End Function
+
+/*!
+@brief	Cのsprintfのような書式化関数7引数版
+@author	Egtra
+@date	2007/10/27
+@param[in] format	書式指定
+@param[in] paramN	引数
+@return 書式化された文字列
+*/
+Function SPrintf(format As String, param0 As Object,
+	param1 As Object, param2 As Object, param3 As Object,
+	param4 As Object, param5 As Object, param6 As Object) As String
+#ifdef _WIN64
+	Dim params[6] = [param0, param1, param2, param3, param4,
+		param5, param6] As Object
+#else
+	Dim params = VarPtr(param0) As *Object
+#endif
+	SPrintf = ActiveBasic.Strings.Detail.SPrintf(format, params, 7)
+End Function
+
+/*!
+@brief	Cのsprintfのような書式化関数6引数版
+@author	Egtra
+@date	2007/10/27
+@param[in] format	書式指定
+@param[in] paramN	引数
+@return 書式化された文字列
+*/
+Function SPrintf(format As String, param0 As Object,
+	param1 As Object, param2 As Object, param3 As Object,
+	param4 As Object, param5 As Object) As String
+#ifdef _WIN64
+	Dim params[5] = [param0, param1, param2, param3, param4,
+		param5] As Object
+#else
+	Dim params = VarPtr(param0) As *Object
+#endif
+	SPrintf = ActiveBasic.Strings.Detail.SPrintf(format, params, 6)
+End Function
+
+/*!
+@brief	Cのsprintfのような書式化関数5引数版
+@author	Egtra
+@date	2007/10/27
+@param[in] format	書式指定
+@param[in] paramN	引数
+@return 書式化された文字列
+*/
+Function SPrintf(format As String, param0 As Object,
+	param1 As Object, param2 As Object, param3 As Object,
+	param4 As Object) As String
+#ifdef _WIN64
+	Dim params[4] = [param0, param1, param2, param3, param4] As Object
+#else
+	Dim params = VarPtr(param0) As *Object
+#endif
+	SPrintf = ActiveBasic.Strings.Detail.SPrintf(format, params, 5)
+End Function
+
+/*!
+@brief	Cのsprintfのような書式化関数4引数版
+@author	Egtra
+@date	2007/10/27
+@param[in] format	書式指定
+@param[in] paramN	引数
+@return 書式化された文字列
+*/
+Function SPrintf(format As String, param0 As Object,
+	param1 As Object, param2 As Object, param3 As Object) As String
+#ifdef _WIN64
+	Dim params[3] = [param0, param1, param2, param3] As Object
+#else
+	Dim params = VarPtr(param0) As *Object
+#endif
+	SPrintf = ActiveBasic.Strings.Detail.SPrintf(format, params, 4)
+End Function
+
+/*!
+@brief	Cのsprintfのような書式化関数3引数版
+@author	Egtra
+@date	2007/10/27
+@param[in] format	書式指定
+@param[in] paramN	引数
+@return 書式化された文字列
+*/
+Function SPrintf(format As String, param0 As Object,
+	param1 As Object, param2 As Object) As String
+#ifdef _WIN64
+	Dim params[2] = [param0, param1, param2] As Object
+#else
+	Dim params = VarPtr(param0) As *Object
+#endif
+	SPrintf = ActiveBasic.Strings.Detail.SPrintf(format, params, 3)
+End Function
+
+/*!
+@brief	Cのsprintfのような書式化関数2引数版
+@author	Egtra
+@date	2007/10/27
+@param[in] format	書式指定
+@param[in] paramN	引数
+@return 書式化された文字列
+*/
+Function SPrintf(format As String, param0 As Object,
+	param1 As Object) As String
+#ifdef _WIN64
+	Dim params[1] = [param0, param1] As Object
+#else
+	Dim params = VarPtr(param0) As *Object
+#endif
+	SPrintf = ActiveBasic.Strings.Detail.SPrintf(format, params, 2)
+End Function
+
+/*!
+@brief	Cのsprintfのような書式化関数1引数版
+@author	Egtra
+@date	2007/10/27
+@param[in] format	書式指定
+@param[in] paramN	引数
+@return 書式化された文字列
+*/
+Function SPrintf(format As String, param0 As Object) As String
+	Dim params = VarPtr(param0) As *Object
+	SPrintf = ActiveBasic.Strings.Detail.SPrintf(format, params, 1)
+End Function
+
+/*!
+@brief	Cのsprintfのような書式化関数0引数版
+@author	Egtra
+@date	2007/10/27
+@param[in] format	書式指定
+@param[in] paramN	引数
+@return 書式化された文字列
+*/
+Function SPrintf(format As String) As String
+	SPrintf = ActiveBasic.Strings.Detail.SPrintf(format, 0, 0)
+End Function
 
 End Namespace 'Strings
Index: trunk/Include/Classes/ActiveBasic/Strings/Strings.ab
===================================================================
--- trunk/Include/Classes/ActiveBasic/Strings/Strings.ab	(revision 382)
+++ trunk/Include/Classes/ActiveBasic/Strings/Strings.ab	(revision 383)
@@ -11,15 +11,17 @@
 
 Sub ChrFill(p As PWSTR, n As SIZE_T, c As WCHAR)
-	Dim i As SIZE_T
-	For i = 0 To ELM(n)
+	Dim i = 0 As SIZE_T
+	While i <> n
 		p[i] = c
-	Next
+		i++
+	Wend
 End Sub
 
 Sub ChrFill(p As PSTR, n As SIZE_T, c As SByte)
-	Dim i As SIZE_T
-	For i = 0 To ELM(n)
+	Dim i = 0 As SIZE_T
+	While i <> n
 		p[i] = c
-	Next
+		i++
+	Wend
 End Sub
 
@@ -105,40 +107,44 @@
 
 Function ChrPBrk(str As PCWSTR, cStr As SIZE_T, chars As PCWSTR, cChars As SIZE_T) As SIZE_T
-	Dim i As SIZE_T
-	For i = 0 To ELM(cStr)
+	Dim i = 0 As SIZE_T
+	While i <> cStr
 		If ChrFind(chars, cChars, str[i]) <> -1 Then
 			Return i
 		End If
-	Next
+		i++
+	Wend
 	Return -1 As SIZE_T
 End Function
 
 Function ChrPBrk(str As PCSTR, cStr As SIZE_T, Chars As PCSTR, cChars As SIZE_T) As SIZE_T
-	Dim i As SIZE_T
-	For i = 0 To ELM(cStr)
+	Dim i = 0 As SIZE_T
+	While i <> cStr
 		If ChrFind(Chars, cChars, str[i]) <> -1 Then
 			Return i
 		End If
-	Next
+		i++
+	Wend
 	Return -1 As SIZE_T
 End Function
 
 Function ChrFind(s As PCWSTR, size As SIZE_T, c As WCHAR) As SIZE_T
-	Dim i As SIZE_T
-	For i = 0 To ELM(size)
+	Dim i = 0 As SIZE_T
+	While i <> size
 		If s[i] = c Then
 			Return i
 		End If
-	Next
+		i++
+	Wend
 	Return -1 As SIZE_T
 End Function
 
 Function ChrFind(s As PCSTR, size As SIZE_T, c As CHAR) As SIZE_T
-	Dim i As SIZE_T
-	For i = 0 To ELM(size)
+	Dim i = 0 As SIZE_T
+	While i <> size
 		If s[i] = c Then
 			Return i
 		End If
-	Next
+		i++
+	Wend
 	Return -1 As SIZE_T
 End Function
@@ -210,4 +216,5 @@
 	Loop
 End Function
+
 End Namespace 'Detail
 
Index: trunk/Include/Classes/System/String.ab
===================================================================
--- trunk/Include/Classes/System/String.ab	(revision 382)
+++ trunk/Include/Classes/System/String.ab	(revision 383)
@@ -6,11 +6,18 @@
 
 #ifdef __STRING_IS_NOT_ALWAYS_UNICODE
+
+#ifndef UNICODE
 TypeDef StrChar = Char
-#ifndef UNICODE
 #define __STRING_IS_NOT_UNICODE
 #endif
+
+#endif
+
+#ifndef __STRING_IS_NOT_UNICODE
+TypeDef StrChar = WCHAR
+
+#ifdef UNICODE
+#define __STRING_IS_UNICODE
 #else
-TypeDef StrChar = WCHAR
-#ifndef UNICODE
 #define __STRING_UNICODE_WINDOWS_ANSI
 #endif
@@ -77,5 +84,5 @@
 			Assign(initStr + start, length)
 		End Sub
-		
+
 		Sub String(initStr As String)
 			If Not String.IsNullOrEmpty(initStr) Then
@@ -592,5 +599,5 @@
 			End If
 		End Sub
-		
+
 		Const Sub rangeCheck(start As Long, length As Long)
 			If start < 0 Or start > This.m_Length Or length < 0 Then
Index: trunk/Include/Classes/System/Text/StringBuilder.ab
===================================================================
--- trunk/Include/Classes/System/Text/StringBuilder.ab	(revision 382)
+++ trunk/Include/Classes/System/Text/StringBuilder.ab	(revision 383)
@@ -520,5 +520,5 @@
 		If Not String.IsNullOrEmpty(s) Then
 			s.CopyTo(startIndex, chars, 0, length)
-			size = s.Length
+			size = length
 		End If
 	End Sub
Index: trunk/Include/basic/function.sbp
===================================================================
--- trunk/Include/basic/function.sbp	(revision 382)
+++ trunk/Include/basic/function.sbp	(revision 383)
@@ -174,7 +174,23 @@
 	'Abs = System.Math.Abs(number)
 	If number < 0 then
-		return -number
-	Else
-		return number
+		Abs = -number
+	Else
+		Abs = number
+	End If
+End Function
+
+Function Abs(number As Int64) As Int64
+	If number < 0 then
+		Abs = -number
+	Else
+		Abs = number
+	End If
+End Function
+
+Function Abs(number As Long) As Long
+	If number < 0 then
+		Abs = -number
+	Else
+		Abs = number
 	End If
 End Function
@@ -240,5 +256,5 @@
 
 #ifndef __STRING_IS_NOT_UNICODE
-Function AscW(s As *WCHAR) As UCSCHAR
+Function AscW(s As String) As UCSCHAR
 	If s.Length = 0 Then
 		AscW = 0
Index: trunk/Include/crt.sbp
===================================================================
--- trunk/Include/crt.sbp	(revision 382)
+++ trunk/Include/crt.sbp	(revision 383)
@@ -65,4 +65,13 @@
 #endif
 
+Declare Function strtol CDecl Lib _CrtDllName (s As PCSTR, ByRef endPtr As PSTR, base As Long) As Long
+Declare Function wcstol CDecl Lib _CrtDllName (s As PCWSTR, ByRef endPtr As PWSTR, base As Long) As Long
+
+#ifdef UNICODE
+Declare Function _tcstol CDecl Lib _CrtDllName Alias "wcstol" (s As PCTSTR, ByRef endPtr As PTSTR, base As Long) As Long
+#else
+Declare Function _tcstol CDecl Lib _CrtDllName Alias "strtol" (s As PCTSTR, ByRef endPtr As PTSTR, base As Long) As Long
+#endif
+
 
 #endif '_INC_CRT
Index: trunk/Include/system/string.sbp
===================================================================
--- trunk/Include/system/string.sbp	(revision 382)
+++ trunk/Include/system/string.sbp	(revision 383)
@@ -265,3 +265,9 @@
 End Function
 
+#ifdef __STRING_IS_NOT_UNICODE
+Typedef BoxedStrChar = System.SByte
+#else
+TypeDef BoxedStrChar = System.UInt16
+#endif
+
 #endif '_INC_BASIC_STRING
Index: trunk/TestCase/SimpleTestCase/GCHandleTest.ab
===================================================================
--- trunk/TestCase/SimpleTestCase/GCHandleTest.ab	(revision 382)
+++ trunk/TestCase/SimpleTestCase/GCHandleTest.ab	(revision 383)
@@ -6,15 +6,15 @@
 
 Sub TestMain()
+	Imports System.Runtime.InteropServices
+
 	Dim o = New Object
-	Dim gch = System.Runtime.InteropServices.GCHandle.Alloc(o)
+	Dim gch = GCHandle.Alloc(o)
 	UnitTest("GCHandle.Alloc, Target", o.Equals(gch.Target))
 
-	Dim ip = System.Runtime.InteropServices.GCHandle.ToIntPtr(gch)
+	Dim ip = GCHandle.ToIntPtr(gch)
 	gch = Nothing
 
-	gch = System.Runtime.InteropServices.GCHandle.FromIntPtr(ip)
+	gch = GCHandle.FromIntPtr(ip)
 	UnitTest("GCHandle - IntPtr", o.Equals(gch.Target))
-
-
 End Sub
 
Index: trunk/TestCase/SimpleTestCase/SPrintFTest.ab
===================================================================
--- trunk/TestCase/SimpleTestCase/SPrintFTest.ab	(revision 382)
+++ trunk/TestCase/SimpleTestCase/SPrintFTest.ab	(revision 383)
@@ -1,4 +1,4 @@
 '--------------------------------------------------------------------
-' Test case of SPrintF Function and etc...
+' Test case of SPrintf Function and etc...
 '--------------------------------------------------------------------
 
@@ -8,5 +8,5 @@
 Namespace SPrintFTest
 
-Sub TestMain()
+Sub FormatTest()
 	Dim s = Nothing As String, e As Long, sign As Boolean
 
@@ -19,75 +19,74 @@
 
 	s = FormatFloatE(9.876543e021, 6, 0, None)
-	UnitTest("FormatFloatE(9876543e+21)", s = "9.876543e+21")
+	UnitTest("FormatFloatE(9876543e+21)", s, "9.876543e+21")
 	s = FormatFloatE(7.81250000E-03, 8, 0, Cap)
-	UnitTest("FormatFloatE(7.81250000E-03)", s = "7.81250000E-03")
+	UnitTest("FormatFloatE(7.81250000E-03)", s, "7.81250000E-03")
 
 	s = FormatFloatE(1.2345e67, 4, 15, 0)
-	UnitTest("FormatFloatE(1.2345e+67, field width = 15)", s = "     1.2345e+67")
+	UnitTest("FormatFloatE(1.2345e+67, field width = 15)", s, "     1.2345e+67")
 	s = FormatFloatE(1.2345e67, 4, 15, Zero)
-	UnitTest("FormatFloatE(1.2345e+67, field width = 15, Zero)", s = "000001.2345e+67")
+	UnitTest("FormatFloatE(1.2345e+67, field width = 15, Zero)", s, "000001.2345e+67")
 	s = FormatFloatE(-1.2345e67, 4, 15, 0)
-	UnitTest("FormatFloatE(-1.2345e+67, field width = 15)", s = "    -1.2345e+67")
+	UnitTest("FormatFloatE(-1.2345e+67, field width = 15)", s, "    -1.2345e+67")
 	s = FormatFloatE(-1.2345e67, 4, 15, Zero)
-	UnitTest("FormatFloatE(-1.2345e+67, field width = 15, Zero)", s = "-00001.2345e+67")
+	UnitTest("FormatFloatE(-1.2345e+67, field width = 15, Zero)", s, "-00001.2345e+67")
 	s = FormatFloatE(1.2345e67, 4, 15, Sign)
-	UnitTest("FormatFloatE(1.2345e+67, field width = 15, Sign)", s = "    +1.2345e+67")
+	UnitTest("FormatFloatE(1.2345e+67, field width = 15, Sign)", s, "    +1.2345e+67")
 	s = FormatFloatE(1.2345e67, 4, 15, Zero Or Sign)
-	UnitTest("FormatFloatE(1.2345e+67, field width = 15, Zero Or Sign)", s = "+00001.2345e+67")
+	UnitTest("FormatFloatE(1.2345e+67, field width = 15, Zero Or Sign)", s, "+00001.2345e+67")
 	s = FormatFloatE(1.2345e67, 4, 15, Zero Or Blank)
-	UnitTest("FormatFloatE(1.2345e+67, field width = 15, Zero Or Blank)", s = " 00001.2345e+67")
+	UnitTest("FormatFloatE(1.2345e+67, field width = 15, Zero Or Blank)", s, " 00001.2345e+67")
 	s = FormatFloatE(-1.2345e67, 4, 15, Zero Or Sign)
-	UnitTest("FormatFloatE(-1.2345e+67, field width = 15, Zero Or Sign)", s = "-00001.2345e+67")
+	UnitTest("FormatFloatE(-1.2345e+67, field width = 15, Zero Or Sign)", s, "-00001.2345e+67")
 	s = FormatFloatE(-1.2345e67, 4, 15, Zero Or Blank)
-	UnitTest("FormatFloatE(-1.2345e+67, field width = 15, Zero Or Blank)", s = "-00001.2345e+67")
+	UnitTest("FormatFloatE(-1.2345e+67, field width = 15, Zero Or Blank)", s, "-00001.2345e+67")
 
 	s = FormatFloatE(1.2345e+67, 4, 0, Cap)
-	UnitTest("FormatFloatE(1.2345E+67, Cap)", s = "1.2345E+67")
+	UnitTest("FormatFloatE(1.2345E+67, Cap)", s, "1.2345E+67")
 	s = FormatFloatE(1.2345e67, 3, 0, None)
-	UnitTest("FormatFloatE(1.2345e+67, precision = 3)", s = "1.234e+67")
-
+	UnitTest("FormatFloatE(1.2345e+67, precision = 3)", s, "1.234e+67")
 
 	s = FormatIntegerU(777, 0, 0, None)
-	UnitTest("FormatIntegerU(777)", s = "777")
+	UnitTest("FormatIntegerU(777)", s, "777")
 	s = FormatIntegerU(513, 0, 5, None)
-	UnitTest("FormatIntegerU(513, field width = 5)", s = "  513")
+	UnitTest("FormatIntegerU(513, field width = 5)", s, "  513")
 
 	s = FormatIntegerD(-3, 2, 0, Sign)
-	UnitTest("FormatIntegerD(-3, precision = 2)", s = "-03")
+	UnitTest("FormatIntegerD(-3, precision = 2)", s, "-03")
 	s = FormatIntegerD(3, 0, 5, Sign)
-	UnitTest("FormatIntegerD(+3, field width = 5)", s = "   +3")
+	UnitTest("FormatIntegerD(+3, field width = 5)", s, "   +3")
 
 	s = FormatIntegerO(&o1234567, DWORD_MAX, 0, None)
-	UnitTest("FormatIntegerO(&o1234567)", s = "1234567")
+	UnitTest("FormatIntegerO(&o1234567)", s, "1234567")
 	s = FormatIntegerO(&o1234567, DWORD_MAX, 0, Alt)
-	UnitTest("FormatIntegerO(&o1234567, Alt)", s = "01234567")
+	UnitTest("FormatIntegerO(&o1234567, Alt)", s, "01234567")
 	s = FormatIntegerO(0, DWORD_MAX, 0, Alt)
-	UnitTest("FormatIntegerO(0, Alt)", s = "0")
+	UnitTest("FormatIntegerO(0, Alt)", s, "0")
 
 	s = FormatIntegerX(&hffff, DWORD_MAX, 0, None)
-	UnitTest("FormatIntegerX(&hffff)", s = "ffff")
+	UnitTest("FormatIntegerX(&hffff)", s, "ffff")
 	s = FormatIntegerX(&hffff, DWORD_MAX, 0, Cap)
-	UnitTest("FormatIntegerX(&hffff, Cap)", s = "FFFF")
+	UnitTest("FormatIntegerX(&hffff, Cap)", s, "FFFF")
 	s = FormatIntegerX(&h12345678, DWORD_MAX, 0, Alt)
-	UnitTest("FormatIntegerX(&h12345678, Alt)", s = "0x12345678")
+	UnitTest("FormatIntegerX(&h12345678, Alt)", s, "0x12345678")
 	s = FormatIntegerX(1, 2, 0, Alt Or Cap)
-	UnitTest("FormatIntegerX(1, precision = 2, Alt, Cap)", s = "0X01")
+	UnitTest("FormatIntegerX(1, precision = 2, Alt, Cap)", s, "0X01")
 	s = FormatIntegerX(0, 4, 0, Alt)
-	UnitTest("FormatIntegerX(0, precision = 4, Alt)", s = "0000")
+	UnitTest("FormatIntegerX(0, precision = 4, Alt)", s, "0000")
 
 	s = FormatFloatF(1, 2, 0, None)
-	UnitTest("FormatFloatF(1.00, precision = 2)", s = "1.00")
+	UnitTest("FormatFloatF(1.00, precision = 2)", s, "1.00")
 	s = FormatFloatF(123.456, 3, 0, None)
-	UnitTest("FormatFloatF(123.456, precision = 3)", s = "123.456")
+	UnitTest("FormatFloatF(123.456, precision = 3)", s, "123.456")
 	s = FormatFloatF(2., 0, 0, Alt)
-	UnitTest("FormatFloatF(2., precision = 0, Alt", s = "2.")
+	UnitTest("FormatFloatF(2., precision = 0, Alt", s, "2.")
 	s = FormatFloatF(-1.234e-1, 3, 0, None)
-	UnitTest("FormatFloatF(-1.234e-1, precision = 3) = -0.123", s = "-0.123")
+	UnitTest("FormatFloatF(-1.234e-1, precision = 3) = -0.123", s, "-0.123")
 	s = FormatFloatF(-1.234e-2, 3, 0, None)
-	UnitTest("FormatFloatF(-1.234e-2, precision = 3) = -0.012", s = "-0.012")
+	UnitTest("FormatFloatF(-1.234e-2, precision = 3) = -0.012", s, "-0.012")
 	s = FormatFloatF(-1.234e-3, 3, 0, None)
-	UnitTest("FormatFloatF(-1.234e-3, precision = 3) = -0.001", s = "-0.001")
+	UnitTest("FormatFloatF(-1.234e-3, precision = 3) = -0.001", s, "-0.001")
 	s = FormatFloatF(-1.234e-4, 3, 0, None)
-	UnitTest("FormatFloatF(-1.234e-4, precision = 3) = -0.000", s = "-0.000")
+	UnitTest("FormatFloatF(-1.234e-4, precision = 3) = -0.000", s, "-0.000")
 	'現状では末尾の桁の誤差を制御しきれないので、文字列全体の一致比較を避けている。
 	s = FormatFloatF(12345678901234567e3, 2, 0, None)
@@ -95,13 +94,112 @@
 
 	s = FormatIntegerLO(&hFFFFFFFFFFFFFFFF, 0, 0, Alt)
-	UnitTest("FormatIntegerLO(&hFFFFFFFFFFFFFFFF, Alt) = 01777777777777777777777", s = "01777777777777777777777")
+	UnitTest("FormatIntegerLO(&hFFFFFFFFFFFFFFFF, Alt) = 01777777777777777777777", s, "01777777777777777777777")
 	s = FormatIntegerLX(&h123456789abcdef0, 0, 0, None)
-	UnitTest("FormatIntegerLX(&h123456789abcdef0)", s = "123456789abcdef0")
+	UnitTest("FormatIntegerLX(&h123456789abcdef0)", s, "123456789abcdef0")
 	s = FormatIntegerLU(8589934590 As QWord, DWORD_MAX, 0, None)
-	UnitTest("FormatIntegerLU(8589934590)", s = "8589934590")
+	UnitTest("FormatIntegerLU(8589934590)", s, "8589934590")
 	s = FormatIntegerLD(-8589934590, DWORD_MAX, 0, None)
-	UnitTest("FormatIntegerLD(-8589934590)", s = "-8589934590")
+	UnitTest("FormatIntegerLD(-8589934590)", s, "-8589934590")
+
+	s = FormatFloatG(1.25, DWORD_MAX, 0, None)
+	UnitTest("FormatFloatG(1.25)", s, "1.25")
+	s = FormatFloatG(0.1, 2, 0, None)
+	UnitTest("FormatFloatG(0.1, precision = 2)", s, "0.1")
+	s = FormatFloatG(1.2e+60, DWORD_MAX, 0, None)
+	UnitTest("FormatFloatG(1.2e+60)", s, "1.2e+60")
+	s = FormatFloatG(1.2e-60, DWORD_MAX, 0, None)
+	UnitTest("FormatFloatG(1.2e-60)", s, "1.2e-60")
+	s = FormatFloatG(1.0, 2, 0, Alt)
+	UnitTest("FormatFloatG(1.0, precision = 2, Alt)", s, "1.0")
+	s = FormatFloatG(0.01, 2, 0, Alt)
+	UnitTest("FormatFloatG(0.01, precision = 2, Alt)", s, "0.010")
+	s = FormatFloatG(0.000123456, 4, 0, None)
+	UnitTest("FormatFloatG(0.000123456, precision = 4) = 0.0001234", s, "0.0001234")
+	s = FormatFloatG(0.0000123456, 4, 0, None)
+	UnitTest("FormatFloatG(0.0000123456, precision = 4) = 1.234e-05", s, "1.234e-05")
+
+	s = FormatFloatA(1, DWORD_MAX, 0, None)
+	UnitTest("FormatFloatA(1)", s, "0x1p+0")
+	s = FormatFloatA(2.2250738585072014e-308, DWORD_MAX, 0, None)
+	UnitTest("FormatFloatA(2.2250738585072014e-308) = 0x1p-1022", s, "0x1p-1022")
+	s = FormatFloatA(1.11253692925360070e-308, DWORD_MAX, 0, None)
+	UnitTest("FormatFloatA(1.11253692925360070e-308) = 0x0.fp-1022", s, "0x0.8p-1022")
+	s = FormatFloatA(3.1415926535897932384626433832795, DWORD_MAX, 0, None)
+	UnitTest("FormatFloatA(π) = 0x1.921fb54442d18p+1", s, "0x1.921fb54442d18p+1")
+	s = FormatFloatA(0, DWORD_MAX, 0, None)
+	UnitTest("FormatFloatA(0)", s, "0x0p+0")
+
+	s = FormatString("123456", DWORD_MAX, 0, None)
+	UnitTest(Ex"FormatString(\q123456\q)", s, "123456")
+	s = FormatString("123456", 3, 0, None)
+	UnitTest(Ex"FormatString(\q123456\q, precision = 3) = \q123\q", s, "123")
+	s = FormatString("123456", 3, 6, None)
+	UnitTest(Ex"FormatString(\q123456\q, precision = 3, field width = 6) = \q   123\q",
+		s, "   123")
+
+	s = FormatCharacter(Asc("Y"), DWORD_MAX, 0, None)
+	UnitTest(Ex"FormatCharacter(\qY\q)", s, "Y")
+	s = FormatCharacter(Asc("I"), DWORD_MAX, 3, Left)
+	UnitTest(Ex"FormatCharacter(\qI\q, Left)", s, "I  ")
 End Sub
 
+Sub TestMain()
+	FormatTest()
+
+	Imports System
+
+	UnitTest(Ex"SPrintf(\q123\q)", ActiveBasic.Strings.Detail.SPrintf("'123'", 0, 0), "'123'")
+	UnitTest(Ex"%s, \qhello\q", SPrintf("'%s'", "hello"), "'hello'")
+	UnitTest(Ex"%7s, \qhello\q", SPrintf("'%7s'", "hello"), "'  hello'")
+	UnitTest(Ex"%*s, -7, \qhello\q", SPrintf("'%*s'", New Int32(-7), "hello"), "'hello  '")
+	UnitTest(Ex"%.3s, \qhello\q", SPrintf("'%.3s'", "hello"), "'hel'")
+	UnitTest(Ex"%.*s, 4, \qhello\q", SPrintf("'%.*s'", New Int32(4), "hello"), "'hell'")
+	UnitTest(Ex"%-5.3s, \qhello\q", SPrintf("'%-5.3s'", "hello"), "'hel  '")
+	UnitTest(Ex"%*.*s, 2, 1, \qhello\q", SPrintf("'%*.*s'", New Int32(2), New Int32(1), "hello"), "' h'")
+#ifdef UNICODE
+	UnitTest(Ex"%c, '0'", SPrintf("'%c'", New System.UInt16(&h30)), "'0'")
+#else
+	UnitTest(Ex"%c, '0'", SPrintf("'%c'", New System.SByte(&h30)), "'0'")
+#endif
+	Dim i = Nothing As Object, mi = Nothing As Object
+	i = New Int32(10)
+	mi = New Int32(-10)
+	UnitTest(Ex"%d, 10", SPrintf("'%d'", i), "'10'")
+	UnitTest(Ex"%+d, 10", SPrintf("'%+d'", i), "'+10'")
+	UnitTest(Ex"% d, 10", SPrintf("'% d'", i), "' 10'")
+	UnitTest(Ex"%4d, 10", SPrintf("'%4d'", i), "'  10'")
+	UnitTest(Ex"%4d, -10", SPrintf("'%4d'", mi), "' -10'")
+	UnitTest(Ex"%04d, 10", SPrintf("'%04d'", i), "'0010'")
+	UnitTest(Ex"%04d, -10", SPrintf("'%04d'", mi), "'-010'")
+	UnitTest(Ex"%5.3d, 10", SPrintf("'%5.3d'", i), "'  010'")
+
+	UnitTest(Ex"%i, 10", SPrintf("'%i'", i), "'10'")
+	UnitTest(Ex"%ld, -4294967296", SPrintf("'%ld'", New System.Int64(-4294967296)), "'-4294967296'")
+	UnitTest(Ex"%li, -4294967296", SPrintf("'%li'", New System.Int64(-4294967296)), "'-4294967296'")
+	UnitTest(Ex"%u, 4294967295", SPrintf("'%u'", New UInt32(4294967295)), "'4294967295'")
+	UnitTest(Ex"%lu, 4294967296", SPrintf("'%lu'", New UInt64(4294967296)), "'4294967296'")
+	UnitTest(Ex"%x, ffffffff", SPrintf("'%x'", New UInt32(4294967295)), "'ffffffff'")
+	UnitTest(Ex"%#x, 0xffffffff", SPrintf("'%#x'", New UInt32(4294967295)), "'0xffffffff'")
+	UnitTest(Ex"%&x, &hffffffff", SPrintf("'%&x'", New UInt32(4294967295)), "'&hffffffff'")
+	UnitTest(Ex"%lx, 12345789abcdef", SPrintf("'%lx'", New UInt64(&h12345789abcdef)), "'12345789abcdef'")
+	UnitTest(Ex"%lX, 12345789ABCDEF", SPrintf("'%lX'", New UInt64(&h12345789abcdef)), "'12345789ABCDEF'")
+	Dim o777 = Nothing As Object
+	o777 = New UInt32(&o777)
+	UnitTest(Ex"%o, 777", SPrintf("'%o'", o777), "'777'")
+	UnitTest(Ex"%#o, 0777", SPrintf("'%#o'", o777), "'0777'")
+	UnitTest(Ex"%&o, &o777", SPrintf("'%&o'", o777), "'&o777'")
+	UnitTest(Ex"%&O, &O777", SPrintf("'%&O'", o777), "'&O777'")
+	UnitTest(Ex"%lo, 100000000000", SPrintf("'%lo'", New UInt64(&o100000000000)), "'100000000000'")
+
+	Dim d = Nothing As Object
+	d = New System.Double(123.25)
+	UnitTest(Ex"%g, 123.25", SPrintf("'%g'", d), "'123.25'")
+	UnitTest(Ex"%f, 123.25", SPrintf("'%f'", d), "'123.250000'")
+	UnitTest(Ex"%e, 123.25", SPrintf("'%e'", d), "'1.232500e+02'")
+	UnitTest(Ex"%a, 123.25", SPrintf("'%a'", d), "'0x1.edp+6'")
+
+	UnitTest(Ex"%%", SPrintf("'%%'", d), "'%'")
+End Sub
+
 End Namespace 'SPrintFTest
 
Index: trunk/TestCase/SimpleTestCase/SimpleTestCase.ab
===================================================================
--- trunk/TestCase/SimpleTestCase/SimpleTestCase.ab	(revision 382)
+++ trunk/TestCase/SimpleTestCase/SimpleTestCase.ab	(revision 383)
@@ -11,5 +11,5 @@
 
 Function UnitTest( msg As String, isSuccessful As Boolean )
-	Dim resultStr As String
+	Dim resultStr = Nothing As String
 	If isSuccessful Then
 		resultStr = Ex"OK      "
@@ -29,4 +29,15 @@
 End Function
 
+Function UnitTest( msg As String, test As String, expectation As String)
+	If test = expectation Then
+		Print Ex"OK      "; msg
+	Else
+		SetConsoleTextAttribute(hStdOut, BACKGROUND_RED Or BACKGROUND_GREEN Or BACKGROUND_INTENSITY)
+		Print Ex"FAILURE!"; msg
+		Print "  test string = '" + test + "'"
+		SetConsoleTextAttribute(hStdOut, csbi.wAttributes)
+	End If
+End Function
+
 Print "Please enter any key"
 Dim a As Long
Index: trunk/TestCase/SimpleTestCase/SimpleTestCase.idx
===================================================================
--- trunk/TestCase/SimpleTestCase/SimpleTestCase.idx	(revision 382)
+++ trunk/TestCase/SimpleTestCase/SimpleTestCase.idx	(revision 383)
@@ -30,6 +30,2 @@
 #include "ExceptionTest.ab"
 _ClearNamespaceImported
-
-'リソースファイル
-#include "resource.ab"
-#resource "SimpleTestCase.rc"
Index: trunk/TestCase/SimpleTestCase/SimpleTestCase.pj
===================================================================
--- trunk/TestCase/SimpleTestCase/SimpleTestCase.pj	(revision 382)
+++ trunk/TestCase/SimpleTestCase/SimpleTestCase.pj	(revision 383)
@@ -23,5 +23,5 @@
 #DEBUG_EXE_PATH=
 
-#RESOURCE=SimpleTestCase.rc
+#RESOURCE=0
 
 #SOURCE
