Chapter 12. Output Formatting

Table of Contents

printf
Conversion Specifications
Flag Specifiers
Width and Precision Specifiers
Size Prefixes
Conversion Formats
printa
trace Default Format

printf

The printf function combines the ability to trace data, as if by the trace function, with the ability to output the data and other text in a specific format that you describe. The printf function tells DTrace to trace the data associated with each argument after the first argument, and then to format the results using the rules described by the first printf argument, known as a format string.

The format string is a regular string that contains any number of format conversions, each beginning with the % character, that describe how to format the corresponding argument. The first conversion in the format string corresponds to the second printf argument, the second conversion to the third argument, and so on. All of the text between conversions is printed verbatim. The character following the % conversion character describes the format to use for the corresponding argument.

Unlike printf ( 3C ) , DTrace printf is a built-in function that is recognized by the D compiler. The D compiler provides several useful services for DTrace printf that are not found in the C library printf :

  • The D compiler compares the arguments to the conversions in the format string. If an argument's type is incompatible with the format conversion, the D compiler provides an error message explaining the problem.

  • The D compiler does not require the use of size prefixes with printf format conversions. The C printf routine requires that you indicate the size of arguments by adding prefixes such as %ld for long or %lld for long long. The D compiler knows the size and type of your arguments, so these prefixes are not required in your D printf statements.

  • DTrace provides additional format characters that are useful for debugging and observability. For example, the %a format conversion can be used to print a pointer as a symbol name and offset.

In order to implement these features, the format string in the DTrace printf function must be specified as a string constant in your D program. Format strings may not be dynamic variables of type string.

Conversion Specifications

Each conversion specification in the format string is introduced by the % character, after which the following information appears in sequence:

  • Zero or more flags (in any order), that modify the meaning of the conversion specification as described in the next section.

  • An optional minimum field width. If the converted value has fewer bytes than the field width, the value will be padded with spaces on the left by default, or on the right if the left-adjustment flag (-) is specified. The field width can also be specified as an asterisk (*), in which case the field width is set dynamically based on the value of an additional argument of type int.

  • An optional precision that indicates the minimum number of digits to appear for the d, i, o, u, x, and X conversions (the field is padded with leading zeroes); the number of digits to appear after the radix character for the e, E, and f conversions, the maximum number of significant digits for the g and G conversions; or the maximum number of bytes to be printed from a string by the s conversion. The precision takes the form of a period (.) followed by either an asterisk (*), described below, or a decimal digit string.

  • An optional sequence of size prefixes that indicate the size of the corresponding argument, described in Size Prefixes. The size prefixes are not necessary in D and are provided for compatibility with the C printf function.

  • A conversion specifier that indicates the type of conversion to be applied to the argument.

The printf ( 3C ) function also supports conversion specifications of the form % n $ where n is a decimal integer; DTrace printf does not support this type of conversion specification.

Flag Specifiers

The printf conversion flags are enabled by specifying one or more of the following characters, which may appear in any order:

'

The integer portion of the result of a decimal conversion (%i, %d, %u, %f, %g, or %G) is formatted with thousands grouping characters using the non-monetary grouping character. Some locales, including the POSIX C locale, do not provide non-monetary grouping characters for use with this flag.

-

The result of the conversion is left-justified within the field. The conversion is right-justified if this flag is not specified.

+

The result of signed conversion always begins with a sign (+ or -). If this flag is not specified, the conversion begins with a sign only when a negative value is converted.

space

If the first character of a signed conversion is not a sign or if a signed conversion results in no characters, a space is placed before the result. If the space and + flags both appear, the space flag is ignored.

#

The value is converted to an alternate form if an alternate form is defined for the selected conversion. The alternate formats for conversions are described along with the corresponding conversion.

0

For d, i, o, u, x, X, e, E, f, g, and G conversions, leading zeroes (following any indication of sign or base) are used to pad to the field width. No space padding is performed. If the 0 and - flags both appear, the 0 flag is ignored. For d, i, o, u, x, and X conversions, if a precision is specified, the 0 flag is ignored. If the 0 and ' flags both appear, the grouping characters are inserted before the zero padding.

Width and Precision Specifiers

The minimum field width can be specified as a decimal digit string following any flag specifier, in which case the field width is set to the specified number of columns. The field width can also be specified as asterisk (*) in which case an additional argument of type int is accessed to determine the field width. For example, to print an integer x in a field width determined by the value of the int variable w, you would write the D statement:

printf("%*d", w, x);

The field width can also be specified using a ? character to indicate that the field width should be set based on the number of characters required to format an address in hexadecimal in the data model of the operating system kernel. The width is set to 8 if the kernel is using the 32–bit data model, or to 16 if the kernel is using the 64–bit data model.

The precision for the conversion can be specified as a decimal digit string following a period (.) or by an asterisk (*) following a period. If an asterisk is used to specify the precision, an additional argument of type int prior to the conversion argument is accessed to determine the precision. If both width and precision are specified as asterisks, the order of arguments to printf for the conversion should appear in the following order: width, precision, value.

Size Prefixes

Size prefixes are required in ANSI-C programs that use printf ( 3C ) in order to indicate the size and type of the conversion argument. The D compiler performs this processing for your printf calls automatically, so size prefixes are not required. Although size prefixes are provided for C compatibility, their use is explicitly discouraged in D programs because they bind your code to a particular data model when using derived types. For example, if a typedef is redefined to different integer base types depending on the data model, it is not possible to use a single C conversion that works in both data models without explicitly knowing the two underlying types and including a cast expression, or defining multiple format strings. The D compiler solves this problem automatically by allowing you to omit size prefixes and automatically determining the argument size.

The size prefixes can be placed just prior to the format conversion name and after any flags, widths, and precision specifiers. The size prefixes are as follows:

  • An optional h specifies that a following d, i, o, u, x, or X conversion applies to a short or unsigned short.

  • An optional l specifies that a following d, i, o, u, x, or X conversion applies to a long or unsigned long.

  • An optional ll specifies that a following d, i, o, u, x, or X conversion applies to a long long or unsigned long long.

  • An optional L specifies that a following e, E, f, g, or G conversion applies to a long double.

  • An optional l specifies that a following c conversion applies to a wint_t argument, and that a following s conversion character applies to a pointer to awchar_t argument.

Conversion Formats

Each conversion character sequence results in fetching zero or more arguments. If insufficient arguments are provided for the format string, or if the format string is exhausted and arguments remain, the D compiler issues an appropriate error message. If an undefined conversion format is specified, the D compiler issues an appropriate error message. The conversion character sequences are:

a

The pointer or uintptr_t argument is printed as a kernel symbol name in the form module ` symbol-name plus an optional hexadecimal byte offset. If the value does not fall within the range defined by a known kernel symbol, the value is printed as a hexadecimal integer.

c

The char, short, or int argument is printed as an ASCII character.

C

The char, short, or int argument is printed as an ASCII character if the character is a printable ASCII character. If the character is not a printable character, it is printed using the corresponding escape sequence as shown in Table 2–5.

d

The char, short, int, long, or long long argument is printed as a decimal (base 10) integer. If the argument is signed, it will be printed as a signed value. If the argument is unsigned, it will be printed as an unsigned value. This conversion has the same meaning as i.

e, E

The float, double, or long double argument is converted to the style [-] d . ddd dd , where there is one digit before the radix character and the number of digits after it is equal to the precision. The radix character is non-zero if the argument is non-zero. If the precision is not specified, the default precision value is 6. If the precision is 0 and the # flag is not specified, no radix character appears. The E conversion format produces a number with E instead of e introducing the exponent. The exponent always contains at least two digits. The value is rounded up to the appropriate number of digits.

f

The float, double, or long double argument is converted to the style [-] ddd . ddd , where the number of digits after the radix character is equal to the precision specification. If the precision is not specified, the default precision value is 6. If the precision is 0 and the # flag is not specified, no radix character appears. If a radix character appears, at least one digit appears before it. The value is rounded up to the appropriate number of digits.

g, G

The float, double, or long double argument is printed in the style f or e (or in style E in the case of a G conversion character), with the precision specifying the number of significant digits. If an explicit precision is 0, it is taken as 1. The style used depends on the value converted: style e (or E) is used only if the exponent resulting from the conversion is less than -4 or greater than or equal to the precision. Trailing zeroes are removed from the fractional part of the result. A radix character appears only if it is followed by a digit. If the # flag is specified, trailing zeroes are not removed from the result.

i

The char, short, int, long, or long long argument is printed as a decimal (base 10) integer. If the argument is signed, it will be printed as a signed value. If the argument is unsigned, it will be printed as an unsigned value. This conversion has the same meaning as d.

o

The char, short, int, long, or long long argument is printed as an unsigned octal (base 8) integer. Arguments that are signed or unsigned may be used with this conversion. If the # flag is specified, the precision of the result will be increased if necessary to force the first digit of the result to be a zero.

p

The pointer or uintptr_t argument is printed as a hexadecimal (base 16) integer. D accepts pointer arguments of any type. If the # flag is specified, a non-zero result will have 0x prepended to it.

s

The argument must be an array of char or a string. Bytes from the array or string are read up to a terminating null character or the end of the data and interpreted and printed as ASCII characters. If the precision is not specified, it is taken to be infinite, so all characters up to the first null character are printed. If the precision is specified, only that portion of the character array that will display in the corresponding number of screen columns is printed. If an argument of type char * is to be formatted, it should be cast to string or prefixed with the D stringof operator to indicate that DTrace should trace the bytes of the string and format them.

S

The argument must be an array of char or a string. The argument is processed as if by the %s conversion, but any ASCII characters that are not printable are replaced by the corresponding escape sequence described in Table 2–5.

u

The char, short, int, long, or long long argument is printed as an unsigned decimal (base 10) integer. Arguments that are signed or unsigned may be used with this conversion, and the result is always formatted as unsigned.

wc

The int argument is converted to a wide character (wchar_t) and the resulting wide character is printed.

ws

The argument must be an array of wchar_t. Bytes from the array are read up to a terminating null character or the end of the data and interpreted and printed as wide characters. If the precision is not specified, it is taken to be infinite, so all wide characters up to the first null character are printed. If the precision is specified, only that portion of the wide character array that will display in the corresponding number of screen columns is printed.

x, X

The char, short, int, long, or long long argument is printed as an unsigned hexadecimal (base 16) integer. Arguments that are signed or unsigned may be used with this conversion. If the x form of the conversion is used, the letter digits abcdef are used. If the X form of the conversion is used, the letter digits ABCDEF are used. If the # flag is specified, a non-zero result will have 0x (for %x) or 0X (for %X) prepended to it.

Y

The uint64_t argument is interpreted to be the number of nanoseconds since 00:00 Universal Coordinated Time, January 1, 1970, and is printed in the following cftime ( 3C ) form: “%Y %a %b %e %T %Z.” The current number of nanoseconds since 00:00 UTC, January 1, 1970 is available in the walltimestamp variable.

%

Print a literal % character. No argument is converted. The entire conversion specification must be %%.