Source File
printf.go
Belonging Package
modernc.org/libc
// Copyright 2020 The Libc Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.package libc // import "modernc.org/libc"import ()const (modNone = iotamodHHmodHmodLmodLLmodQmodCapitalLmodJmodZmodCapitalZmodTmod32mod64)// Format of the format string//// The format string is a character string, beginning and ending in its initial// shift state, if any. The format string is composed of zero or more// directives: ordinary characters (not %), which are copied unchanged to// the output stream; and conversion specifications, each of which results in// fetching zero or more subsequent arguments.func (, uintptr) []byte {:= bytes.NewBuffer(nil)for {switch := *(*byte)(unsafe.Pointer()); {case '%':= printfConversion(, , &)case 0:// if dmesgs {// dmesg("%v: %q", origin(1), buf.Bytes())// }return .Bytes()default:++.WriteByte()}}}// Each conversion specification is introduced by the character %, and ends// with a conversion specifier. In between there may be (in this order) zero// or more flags, an optional minimum field width, an optional precision and// an optional length modifier.func ( *bytes.Buffer, uintptr, *uintptr) uintptr {++ // '%':= "%"// Flags characters//// The character % is followed by zero or more of the following flags::for {switch := *(*byte)(unsafe.Pointer()); {case '#':// The value should be converted to an "alternate form". For o conversions,// the first character of the output string is made zero (by prefixing a 0 if// it was not zero already). For x and X conversions, a nonzero result has// the string "0x" (or "0X" for X conversions) prepended to it. For a, A, e,// E, f, F, g, and G conversions, the result will always contain a decimal// point, even if no digits follow it (normally, a decimal point appears in the// results of those conversions only if a digit follows). For g and G// conversions, trailing zeros are not removed from the result as they would// otherwise be. For other conversions, the result is undefined.+++= "#"case '0':// The value should be zero padded. For d, i, o, u, x, X, a, A, e, E, f, F,// g, and G conversions, the converted value is padded on the left with zeros// rather than blanks. If the 0 and - flags both appear, the 0 flag is// ignored. If a precision is given with a numeric conversion (d, i, o, u, x,// and X), the 0 flag is ignored. For other conversions, the behav‐ ior is// undefined.+++= "0"case '-':// The converted value is to be left adjusted on the field boundary. (The// default is right justification.) The converted value is padded on the right// with blanks, rather than on the left with blanks or zeros. A - overrides a// 0 if both are given.+++= "-"case ' ':// A blank should be left before a positive number (or empty string) produced// by a signed conversion.+++= " "case '+':// A sign (+ or -) should always be placed before a number produced by a signed// conversion. By default, a sign is used only for negative numbers. A +// overrides a space if both are used.+++= "+"default:break}}, , := parseFieldWidth()if {+= strconv.Itoa()}, , := parsePrecision(, ), := parseLengthModifier()var string:// Conversion specifiers//// A character that specifies the type of conversion to be applied. The// conversion specifiers and their meanings are:switch := *(*byte)(unsafe.Pointer()); {case 'd', 'i':// The int argument is converted to signed decimal notation. The precision,// if any, gives the minimum number of digits that must appear; if the// converted value requires fewer digits, it is padded on the left with zeros.// The default precision is 1. When 0 is printed with an explicit precision 0,// the output is empty.++var int64switch {case modNone, modL, modLL, mod64:= VaInt64()case modH:= int64(int16(VaInt32()))case modHH:= int64(int8(VaInt32()))case mod32:= int64(VaInt32())default:panic(todo("", ))}if == 0 && && == 0 {break}if {panic(todo("", ))}:= + "d"= fmt.Sprintf(, )case 'u':// The unsigned int argument is converted to unsigned decimal notation. The// precision, if any, gives the minimum number of digits that must appear; if// the converted value requires fewer digits, it is padded on the left with// zeros. The default precision is 1. When 0 is printed with an explicit// precision 0, the output is empty.++var uint64switch {case modNone, modL, modLL, mod64:= VaUint64()case modH:= uint64(uint16(VaInt32()))case modHH:= uint64(uint8(VaInt32()))case mod32:= uint64(VaInt32())default:panic(todo("", ))}if == 0 && && == 0 {break}if {panic(todo("", ))}:= + "d"= fmt.Sprintf(, )case 'o':// The unsigned int argument is converted to unsigned octal notation. The// precision, if any, gives the minimum number of digits that must appear; if// the converted value requires fewer digits, it is padded on the left with// zeros. The default precision is 1. When 0 is printed with an explicit// precision 0, the output is empty.++var uint64switch {case modNone, modL, modLL, mod64:= VaUint64()case modH:= uint64(uint16(VaInt32()))case modHH:= uint64(uint8(VaInt32()))case mod32:= uint64(VaInt32())default:panic(todo("", ))}if == 0 && && == 0 {break}if {panic(todo("", ))}:= + "o"= fmt.Sprintf(, )case 'I':if !isWindows {panic(todo("%#U", ))}++switch = *(*byte)(unsafe.Pointer()); {case 'x', 'X':// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-wsprintfa//// Ix, IX//// 64-bit unsigned hexadecimal integer in lowercase or uppercase on 64-bit// platforms, 32-bit unsigned hexadecimal integer in lowercase or uppercase on// 32-bit platforms.if unsafe.Sizeof(int(0)) == 4 {= mod32}case '3':// https://en.wikipedia.org/wiki/Printf_format_string#Length_field//// I32 For integer types, causes printf to expect a 32-bit (double word) integer argument.++switch = *(*byte)(unsafe.Pointer()); {case '2':++= mod32gotodefault:panic(todo("%#U", ))}case '6':// https://en.wikipedia.org/wiki/Printf_format_string#Length_field//// I64 For integer types, causes printf to expect a 64-bit (quad word) integer argument.++switch = *(*byte)(unsafe.Pointer()); {case '4':++= mod64gotodefault:panic(todo("%#U", ))}default:panic(todo("%#U", ))}fallthroughcase 'X':fallthroughcase 'x':// The unsigned int argument is converted to unsigned hexadecimal notation.// The letters abcdef are used for x conversions; the letters ABCDEF are used// for X conversions. The precision, if any, gives the minimum number of// digits that must appear; if the converted value requires fewer digits, it is// padded on the left with zeros. The default precision is 1. When 0 is// printed with an explicit precision 0, the output is empty.++var uint64switch {case modNone, modL, modLL, mod64:= VaUint64()case modH:= uint64(uint16(VaInt32()))case modHH:= uint64(uint8(VaInt32()))case mod32:= uint64(VaInt32())default:panic(todo("", ))}if == 0 && && == 0 {break}if strings.Contains(, "#") && == 0 {= strings.ReplaceAll(, "#", "")}var stringswitch {case := fmt.Sprintf("%s.%d%c", , , )default:= + string()}= fmt.Sprintf(, )case 'e', 'E':// The double argument is rounded and converted in the style [-]d.ddde±dd where// there is one digit before the decimal-point character and the number of// digits after it is equal to the precision; if the precision is missing, it// is taken as 6; if the precision is zero, no decimal-point character appears.// An E conversion uses the letter E (rather than e) to intro‐ duce the// exponent. The exponent always contains at least two digits; if the value is// zero, the exponent is 00.++:= VaFloat64()if ! {= 6}:= fmt.Sprintf("%s.%d%c", , , )= fmt.Sprintf(, )case 'f', 'F':// The double argument is rounded and converted to decimal notation in the// style [-]ddd.ddd, where the number of digits after the decimal-point// character is equal to the precision specification. If the precision// is missing, it is taken as 6; if the precision is explicitly zero, no// decimal-point character appears. If a decimal point appears, at least one// digit appears before it.++:= VaFloat64()if ! {= 6}:= fmt.Sprintf("%s.%d%c", , , )= fmt.Sprintf(, )case 'G':fallthroughcase 'g':// The double argument is converted in style f or e (or F or E for G// conversions). The precision specifies the number of significant digits. If// the precision is missing, 6 digits are given; if the precision is zero, it// is treated as 1. Style e is used if the exponent from its conversion is// less than -4 or greater than or equal to the precision. Trailing zeros are// removed from the fractional part of the result; a decimal point appears only// if it is followed by at least one digit.++:= VaFloat64()if ! {= 6}if == 0 {= 1}:= fmt.Sprintf("%s.%d%c", , , )= fmt.Sprintf(, )case 's':// If no l modifier is present: the const char * argument is expected to be a// pointer to an array of character type (pointer to a string). Characters// from the array are written up to (but not including) a terminating null byte// ('\0'); if a precision is specified, no more than the number specified are// written. If a precision is given, no null byte need be present; if// the precision is not specified, or is greater than the size of the array,// the array must contain a terminating null byte.//// If an l modifier is present: the const wchar_t * argument is expected// to be a pointer to an array of wide characters. Wide characters from the// array are converted to multibyte characters (each by a call to the// wcrtomb(3) function, with a conversion state starting in the initial state// before the first wide character), up to and including a terminating null// wide character. The resulting multibyte characters are written up to// (but not including) the terminating null byte. If a precision is specified,// no more bytes than the number specified are written, but no partial// multibyte characters are written. Note that the precision determines the// number of bytes written, not the number of wide characters or screen// positions. The array must contain a terminating null wide character,// unless a precision is given and it is so small that the number of bytes// written exceeds it before the end of the array is reached.++:= VaUintptr()switch {case modNone:var stringswitch {case := fmt.Sprintf("%s.%ds", , )= fmt.Sprintf(, GoBytes(, ))default:= + "s"= fmt.Sprintf(, GoString())}default:panic(todo(""))}case 'p':// The void * pointer argument is printed in hexadecimal (as if by %#x or// %#lx).++:= VaUintptr().WriteString("0x").WriteString(strconv.FormatInt(int64(), 16))case 'c':// If no l modifier is present, the int argument is converted to an unsigned// char, and the resulting character is written. If an l modifier is present,// the wint_t (wide character) ar‐ gument is converted to a multibyte sequence// by a call to the wcrtomb(3) function, with a conversion state starting in// the initial state, and the resulting multibyte string is writ‐ ten.++switch {case modNone::= VaInt32().WriteByte(byte())default:panic(todo(""))}case '%':// A '%' is written. No argument is converted. The complete conversion// specification is '%%'.++.WriteByte('%')default:panic(todo("%#U", ))}.WriteString()return}// Field width//// An optional decimal digit string (with nonzero first digit) specifying a// minimum field width. If the converted value has fewer characters than the// field width, it will be padded with spa‐ ces on the left (or right, if the// left-adjustment flag has been given). Instead of a decimal digit string one// may write "*" or "*m$" (for some decimal integer m) to specify that the// field width is given in the next argument, or in the m-th argument,// respectively, which must be of type int. A negative field width is taken as// a '-' flag followed by a positive field width. In no case does a// nonexistent or small field width cause truncation of a field; if the result// of a conversion is wider than the field width, the field is expanded to// contain the conversion result.func ( uintptr) ( uintptr, int, bool) {:= truefor {var intswitch := *(*byte)(unsafe.Pointer()); {case && == '0':return , ,case && == '*':panic(todo(""))case >= '0' && <= '9':++= true= false= int() - '0'default:return , ,}:== 10* +if < {panic(todo(""))}}}// Precision//// An optional precision, in the form of a period ('.') followed by an// optional decimal digit string. Instead of a decimal digit string one may// write "*" or "*m$" (for some decimal integer m) to specify that the// precision is given in the next argument, or in the m-th argument,// respectively, which must be of type int. If the precision is given as just// '.', the precision is taken to be zero. A negative precision is taken// as if the precision were omitted. This gives the minimum number of digits// to appear for d, i, o, u, x, and X conversions, the number of digits to// appear after the radix character for a, A, e, E, f, and F conversions, the// maximum number of significant digits for g and G conversions, or the maximum// number of characters to be printed from a string for s and S conversions.func ( uintptr, *uintptr) ( uintptr, int, bool) {for {switch := *(*byte)(unsafe.Pointer()); {case '.':++:= truefor {switch := *(*byte)(unsafe.Pointer()); {case && == '*':++= int(VaInt32())return , , truecase >= '0' && <= '9':++= false:== 10* + (int() - '0')if < {panic(todo(""))}default:return , , true}}default:return , 0, false}}}// Length modifier//// Here, "integer conversion" stands for d, i, o, u, x, or X conversion.//// hh A following integer conversion corresponds to a signed char or// unsigned char argument, or a following n conversion corresponds to a pointer// to a signed char argument.//// h A following integer conversion corresponds to a short int or unsigned// short int argument, or a following n conversion corresponds to a pointer to// a short int argument.//// l (ell) A following integer conversion corresponds to a long int or// unsigned long int argument, or a following n conversion corresponds to a// pointer to a long int argument, or a fol‐ lowing c conversion corresponds to// a wint_t argument, or a following s conversion corresponds to a pointer to// wchar_t argument.//// ll (ell-ell). A following integer conversion corresponds to a long long// int or unsigned long long int argument, or a following n conversion// corresponds to a pointer to a long long int argument.//// q A synonym for ll. This is a nonstandard extension, derived from BSD;// avoid its use in new code.//// L A following a, A, e, E, f, F, g, or G conversion corresponds to a// long double argument. (C99 allows %LF, but SUSv2 does not.)//// j A following integer conversion corresponds to an intmax_t or// uintmax_t argument, or a following n conversion corresponds to a pointer to// an intmax_t argument.//// z A following integer conversion corresponds to a size_t or ssize_t// argument, or a following n conversion corresponds to a pointer to a size_t// argument.//// Z A nonstandard synonym for z that predates the appearance of z. Do// not use in new code.//// t A following integer conversion corresponds to a ptrdiff_t argument,// or a following n conversion corresponds to a pointer to a ptrdiff_t// argument.func ( uintptr) ( uintptr, int) {switch := *(*byte)(unsafe.Pointer()); {case 'h':++= modHswitch := *(*byte)(unsafe.Pointer()); {case 'h':++= modHH}return ,case 'l':++= modLswitch := *(*byte)(unsafe.Pointer()); {case 'l':++= modLL}return ,case 'q':panic(todo(""))case 'L':panic(todo(""))case 'j':panic(todo(""))case 'z':panic(todo(""))case 'Z':panic(todo(""))case 't':panic(todo(""))default:return , 0}}
![]() |
The pages are generated with Golds v0.3.6. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |