}\r
\r
/**\r
- Internal function that convert a decimal number to a string in Buffer.\r
+ Internal function that convert a number to a string in Buffer.\r
\r
- Print worker function that convert a decimal number to a string in Buffer.\r
+ Print worker function that converts a decimal or hexadecimal number to an ASCII string in Buffer.\r
\r
- @param Buffer Location to place the Unicode or ASCII string of Value.\r
+ @param Buffer Location to place the ASCII string of Value.\r
@param Value Value to convert to a Decimal or Hexadecimal string in Buffer.\r
@param Radix Radix of the value\r
\r
- @return Number of characters printed.\r
+ @return A pointer to the end of buffer filled with ASCII string.\r
\r
**/\r
-UINTN\r
+CHAR8 *\r
BasePrintLibValueToString (\r
IN OUT CHAR8 *Buffer, \r
IN INT64 Value, \r
IN UINTN Radix\r
)\r
{\r
- UINTN Digits;\r
UINT32 Remainder;\r
\r
//\r
// Loop to convert one digit at a time in reverse order\r
//\r
- *(Buffer++) = 0;\r
- Digits = 0;\r
+ *Buffer = 0;\r
do {\r
Value = (INT64)DivU64x32Remainder ((UINT64)Value, (UINT32)Radix, &Remainder);\r
- *(Buffer++) = mHexStr[Remainder];\r
- Digits++;\r
+ *(++Buffer) = mHexStr[Remainder];\r
} while (Value != 0);\r
\r
//\r
- // the length of Buffer string converted from Value\r
+ // Return pointer of the end of filled buffer.\r
//\r
- return Digits;\r
+ return Buffer;\r
}\r
\r
/**\r
CHAR8 *OriginalBuffer;\r
CHAR8 *EndBuffer;\r
CHAR8 ValueBuffer[MAXIMUM_VALUE_CHARACTERS];\r
+ CHAR8 *ValueBufferPtr;\r
UINTN Count;\r
UINTN Digits;\r
UINTN Index;\r
// Count the length of the value string.\r
//\r
Radix = ((Flags & RADIX_HEX) == 0)? 10 : 16;\r
- Count = BasePrintLibValueToString (ValueBuffer, Value, Radix);\r
+ ValueBufferPtr = BasePrintLibValueToString (ValueBuffer, Value, Radix);\r
+ Count = ValueBufferPtr - ValueBuffer;\r
\r
//\r
// Append Zero\r
Digits = 3 - Digits;\r
}\r
for (Index = 0; Index < Count; Index++) {\r
- Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, ValueBuffer[Count - Index], Increment);\r
+ Buffer = BasePrintLibFillBuffer (Buffer, EndBuffer, 1, *ValueBufferPtr--, Increment);\r
if ((Flags & COMMA_TYPE) != 0) {\r
Digits++;\r
if (Digits == 3) {\r
based on a Null-terminated format string and a VA_LIST argument list.\r
\r
VSPrint function to process format and place the results in Buffer. Since a \r
- VA_LIST is used this rountine allows the nesting of Vararg routines. Thus \r
+ VA_LIST is used this routine allows the nesting of Vararg routines. Thus \r
this is the main print working routine.\r
\r
- @param Buffer Character buffer to print the results of the parsing\r
- of Format into.\r
- @param BufferSize Maximum number of characters to put into buffer.\r
- @param Flags Intial flags value.\r
- Can only have FORMAT_UNICODE and OUTPUT_UNICODE set.\r
- @param Format Null-terminated format string.\r
- @param Marker Vararg list consumed by processing Format.\r
+ @param Buffer Character buffer to print the results of the parsing\r
+ of Format into.\r
+ @param BufferSize Maximum number of characters to put into buffer.\r
+ @param Flags Initial flags value.\r
+ Can only have FORMAT_UNICODE and OUTPUT_UNICODE set.\r
+ @param Format Null-terminated format string.\r
+ @param VaListMarker VA_LIST style variable argument list consumed by processing Format.\r
+ @param BaseListMarker BASE_LIST style variable argument list consumed by processing Format.\r
\r
@return Number of characters printed not including the Null-terminator.\r
\r
**/\r
UINTN\r
-BasePrintLibVSPrint (\r
+BasePrintLibSPrintMarker (\r
OUT CHAR8 *Buffer,\r
IN UINTN BufferSize,\r
IN UINTN Flags,\r
IN CONST CHAR8 *Format,\r
- IN VA_LIST Marker\r
+ IN VA_LIST VaListMarker, OPTIONAL\r
+ IN BASE_LIST BaseListMarker OPTIONAL\r
)\r
{\r
- CHAR8 *OriginalBuffer;\r
- CHAR8 *EndBuffer;\r
- CHAR8 ValueBuffer[MAXIMUM_VALUE_CHARACTERS];\r
- UINTN BytesPerOutputCharacter;\r
- UINTN BytesPerFormatCharacter;\r
- UINTN FormatMask;\r
- UINTN FormatCharacter;\r
- UINTN Width;\r
- UINTN Precision;\r
- INT64 Value;\r
- CONST CHAR8 *ArgumentString;\r
- UINTN Character;\r
- GUID *TmpGuid;\r
- TIME *TmpTime;\r
- UINTN Count;\r
- UINTN ArgumentMask;\r
- INTN BytesPerArgumentCharacter;\r
- UINTN ArgumentCharacter;\r
- BOOLEAN Done;\r
- UINTN Index;\r
- CHAR8 Prefix;\r
- BOOLEAN ZeroPad;\r
- BOOLEAN Comma;\r
- UINTN Digits;\r
- UINTN Radix;\r
- RETURN_STATUS Status;\r
+ CHAR8 *OriginalBuffer;\r
+ CHAR8 *EndBuffer;\r
+ CHAR8 ValueBuffer[MAXIMUM_VALUE_CHARACTERS];\r
+ UINTN BytesPerOutputCharacter;\r
+ UINTN BytesPerFormatCharacter;\r
+ UINTN FormatMask;\r
+ UINTN FormatCharacter;\r
+ UINTN Width;\r
+ UINTN Precision;\r
+ INT64 Value;\r
+ CONST CHAR8 *ArgumentString;\r
+ UINTN Character;\r
+ GUID *TmpGuid;\r
+ TIME *TmpTime;\r
+ UINTN Count;\r
+ UINTN ArgumentMask;\r
+ INTN BytesPerArgumentCharacter;\r
+ UINTN ArgumentCharacter;\r
+ BOOLEAN Done;\r
+ UINTN Index;\r
+ CHAR8 Prefix;\r
+ BOOLEAN ZeroPad;\r
+ BOOLEAN Comma;\r
+ UINTN Digits;\r
+ UINTN Radix;\r
+ RETURN_STATUS Status;\r
\r
if (BufferSize == 0) {\r
return 0;\r
//\r
BufferSize--;\r
OriginalBuffer = Buffer;\r
+\r
//\r
// Set the tag for the end of the input Buffer.\r
//\r
FormatMask = 0xff;\r
}\r
\r
-\r
-\r
//\r
// Get the first character from the format string\r
//\r
case '*':\r
if ((Flags & PRECISION) == 0) {\r
Flags |= PAD_TO_WIDTH;\r
- Width = VA_ARG (Marker, UINTN);\r
+ if (BaseListMarker == NULL) {\r
+ Width = VA_ARG (VaListMarker, UINTN);\r
+ } else {\r
+ Width = BASE_ARG (BaseListMarker, UINTN);\r
+ }\r
} else {\r
- Precision = VA_ARG (Marker, UINTN);\r
+ if (BaseListMarker == NULL) {\r
+ Precision = VA_ARG (VaListMarker, UINTN);\r
+ } else {\r
+ Precision = BASE_ARG (BaseListMarker, UINTN);\r
+ }\r
}\r
break;\r
case '0':\r
//\r
case 'd':\r
if ((Flags & LONG_TYPE) == 0) {\r
- Value = (VA_ARG (Marker, int));\r
+ //\r
+ // 'd','x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".\r
+ // This assumption is made so the format string definition is compatible with the ANSI C\r
+ // Specification for formatted strings. It is recommended that the Base Types be used \r
+ // everywhere, but in this one case, compliance with ANSI C is more important, and \r
+ // provides an implementation that is compatible with that largest possible set of CPU \r
+ // architectures. This is why the type "int" is used in this one case.\r
+ //\r
+ if (BaseListMarker == NULL) {\r
+ Value = VA_ARG (VaListMarker, int);\r
+ } else {\r
+ Value = BASE_ARG (BaseListMarker, int);\r
+ }\r
} else {\r
- Value = VA_ARG (Marker, INT64);\r
+ if (BaseListMarker == NULL) {\r
+ Value = VA_ARG (VaListMarker, INT64);\r
+ } else {\r
+ Value = BASE_ARG (BaseListMarker, INT64);\r
+ }\r
}\r
if ((Flags & PREFIX_BLANK) != 0) {\r
Prefix = ' ';\r
Radix = 16;\r
Comma = FALSE;\r
if ((Flags & LONG_TYPE) == 0 && Value < 0) {\r
+ //\r
+ // 'd','x', and 'X' that are not preceded by 'l' or 'L' are assumed to be type "int".\r
+ // This assumption is made so the format string definition is compatible with the ANSI C\r
+ // Specification for formatted strings. It is recommended that the Base Types be used \r
+ // everywhere, but in this one case, compliance with ANSI C is more important, and \r
+ // provides an implementation that is compatible with that largest possible set of CPU \r
+ // architectures. This is why the type "unsigned int" is used in this one case.\r
+ //\r
Value = (unsigned int)Value;\r
}\r
}\r
//\r
// Convert Value to a reversed string\r
//\r
- Count = BasePrintLibValueToString (ValueBuffer, Value, Radix);\r
+ Count = BasePrintLibValueToString (ValueBuffer, Value, Radix) - ValueBuffer;\r
if (Value == 0 && Precision == 0) {\r
Count = 0;\r
}\r
// break skipped on purpose\r
//\r
case 'a':\r
- ArgumentString = (CHAR8 *)VA_ARG (Marker, CHAR8 *);\r
+ if (BaseListMarker == NULL) {\r
+ ArgumentString = VA_ARG (VaListMarker, CHAR8 *);\r
+ } else {\r
+ ArgumentString = BASE_ARG (BaseListMarker, CHAR8 *);\r
+ }\r
if (ArgumentString == NULL) {\r
Flags &= (~ARGUMENT_UNICODE);\r
ArgumentString = "<null string>";\r
break;\r
\r
case 'c':\r
- Character = VA_ARG (Marker, UINTN) & 0xffff;\r
+ if (BaseListMarker == NULL) {\r
+ Character = VA_ARG (VaListMarker, UINTN) & 0xffff;\r
+ } else {\r
+ Character = BASE_ARG (BaseListMarker, UINTN) & 0xffff;\r
+ }\r
ArgumentString = (CHAR8 *)&Character;\r
Flags |= ARGUMENT_UNICODE;\r
break;\r
\r
case 'g':\r
- TmpGuid = VA_ARG (Marker, GUID *);\r
+ if (BaseListMarker == NULL) {\r
+ TmpGuid = VA_ARG (VaListMarker, GUID *);\r
+ } else {\r
+ TmpGuid = BASE_ARG (BaseListMarker, GUID *);\r
+ }\r
if (TmpGuid == NULL) {\r
ArgumentString = "<null guid>";\r
} else {\r
break;\r
\r
case 't':\r
- TmpTime = VA_ARG (Marker, TIME *); \r
+ if (BaseListMarker == NULL) {\r
+ TmpTime = VA_ARG (VaListMarker, TIME *); \r
+ } else {\r
+ TmpTime = BASE_ARG (BaseListMarker, TIME *); \r
+ }\r
if (TmpTime == NULL) {\r
ArgumentString = "<null time>";\r
} else {\r
break;\r
\r
case 'r':\r
- Status = VA_ARG (Marker, RETURN_STATUS);\r
+ if (BaseListMarker == NULL) {\r
+ Status = VA_ARG (VaListMarker, RETURN_STATUS);\r
+ } else {\r
+ Status = BASE_ARG (BaseListMarker, RETURN_STATUS);\r
+ }\r
ArgumentString = ValueBuffer;\r
if (RETURN_ERROR (Status)) {\r
//\r
based on a Null-terminated format string and variable argument list.\r
\r
VSPrint function to process format and place the results in Buffer. Since a \r
- VA_LIST is used this rountine allows the nesting of Vararg routines. Thus \r
+ VA_LIST is used this routine allows the nesting of Vararg routines. Thus \r
this is the main print working routine\r
\r
@param StartOfBuffer Character buffer to print the results of the parsing\r
of Format into.\r
@param BufferSize Maximum number of characters to put into buffer.\r
Zero means no limit.\r
- @param Flags Intial flags value.\r
+ @param Flags Initial flags value.\r
Can only have FORMAT_UNICODE and OUTPUT_UNICODE set\r
@param FormatString Null-terminated format string.\r
@param ... The variable argument list.\r
VA_LIST Marker;\r
\r
VA_START (Marker, FormatString);\r
- return BasePrintLibVSPrint (StartOfBuffer, BufferSize, Flags, FormatString, Marker);\r
+ return BasePrintLibSPrintMarker (StartOfBuffer, BufferSize, Flags, FormatString, Marker, NULL);\r
}\r