diff options
Diffstat (limited to 'vendor/modernc.org/libc/scanf.go')
-rw-r--r-- | vendor/modernc.org/libc/scanf.go | 237 |
1 files changed, 177 insertions, 60 deletions
diff --git a/vendor/modernc.org/libc/scanf.go b/vendor/modernc.org/libc/scanf.go index 3c5745f47..ebc3ada91 100644 --- a/vendor/modernc.org/libc/scanf.go +++ b/vendor/modernc.org/libc/scanf.go @@ -2,13 +2,14 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build !(linux && (amd64 || loong64)) +//go:build !(linux && (amd64 || arm64 || loong64)) package libc // import "modernc.org/libc" import ( "io" "strconv" + "strings" "unsafe" ) @@ -86,6 +87,7 @@ func scanfConversion(r io.ByteScanner, format uintptr, args *uintptr) (_ uintptr mod := 0 width := -1 + discard := false flags: for { switch c := *(*byte)(unsafe.Pointer(format)); c { @@ -95,7 +97,7 @@ flags: // corresponding pointer argument is re‐ quired, and this specification is not // included in the count of successful assignments returned by scanf(). format++ - panic(todo("")) + discard = true case '\'': // For decimal conversions, an optional quote character ('). This specifies // that the input number may include thousands' separators as defined by the @@ -143,7 +145,18 @@ flags: // input '%' character. No conversion is done (but initial white space // characters are discarded), and assign‐ ment does not occur. format++ - panic(todo("")) + skipReaderWhiteSpace(r) + c, err := r.ReadByte() + if err != nil { + return format, -1, false + } + + if c == '%' { + return format, 1, true + } + + r.UnreadByte() + return format, 0, false case 'd': // Matches an optionally signed decimal integer; the next pointer must be a // pointer to int. @@ -193,22 +206,26 @@ flags: break } - arg := VaUintptr(args) - v := int64(n) - if neg { - v = -v - } - switch mod { - case modNone: - *(*int32)(unsafe.Pointer(arg)) = int32(v) - case modH: - *(*int16)(unsafe.Pointer(arg)) = int16(v) - case modHH: - *(*int8)(unsafe.Pointer(arg)) = int8(v) - case modL: - *(*long)(unsafe.Pointer(arg)) = long(n) - default: - panic(todo("")) + if !discard { + arg := VaUintptr(args) + v := int64(n) + if neg { + v = -v + } + switch mod { + case modNone: + *(*int32)(unsafe.Pointer(arg)) = int32(v) + case modH: + *(*int16)(unsafe.Pointer(arg)) = int16(v) + case modHH: + *(*int8)(unsafe.Pointer(arg)) = int8(v) + case modL: + *(*long)(unsafe.Pointer(arg)) = long(v) + case modLL: + *(*int64)(unsafe.Pointer(arg)) = int64(v) + default: + panic(todo("", mod)) + } } nvalues = 1 case 'D': @@ -246,7 +263,7 @@ flags: for ; width != 0; width-- { c, err := r.ReadByte() if err != nil { - if match { + if match || err == io.EOF { break hex } @@ -286,18 +303,20 @@ flags: break } - arg := VaUintptr(args) - switch mod { - case modNone: - *(*uint32)(unsafe.Pointer(arg)) = uint32(n) - case modH: - *(*uint16)(unsafe.Pointer(arg)) = uint16(n) - case modHH: - *(*byte)(unsafe.Pointer(arg)) = byte(n) - case modL: - *(*ulong)(unsafe.Pointer(arg)) = ulong(n) - default: - panic(todo("")) + if !discard { + arg := VaUintptr(args) + switch mod { + case modNone: + *(*uint32)(unsafe.Pointer(arg)) = uint32(n) + case modH: + *(*uint16)(unsafe.Pointer(arg)) = uint16(n) + case modHH: + *(*byte)(unsafe.Pointer(arg)) = byte(n) + case modL: + *(*ulong)(unsafe.Pointer(arg)) = ulong(n) + default: + panic(todo("")) + } } nvalues = 1 case 'f', 'e', 'g', 'E', 'a': @@ -323,17 +342,19 @@ flags: panic(todo("", err)) } - arg := VaUintptr(args) - if neg { - n = -n - } - switch mod { - case modNone: - *(*float32)(unsafe.Pointer(arg)) = float32(n) - case modL: - *(*float64)(unsafe.Pointer(arg)) = n - default: - panic(todo("", mod, neg, n)) + if !discard { + arg := VaUintptr(args) + if neg { + n = -n + } + switch mod { + case modNone: + *(*float32)(unsafe.Pointer(arg)) = float32(n) + case modL: + *(*float64)(unsafe.Pointer(arg)) = n + default: + panic(todo("", mod, neg, n)) + } } return format, 1, true case 's': @@ -342,8 +363,44 @@ flags: // hold the input sequence and the terminating null byte ('\0'), which is added // automatically. The input string stops at white space or at the maximum // field width, whichever occurs first. - format++ - panic(todo("")) + var c byte + var err error + var arg uintptr + if !discard { + arg = VaUintptr(args) + } + scans: + for ; width != 0; width-- { + if c, err = r.ReadByte(); err != nil { + if err != io.EOF { + nvalues = -1 + } + break scans + } + + switch c { + case ' ', '\t', '\n', '\r', '\v', '\f': + break scans + } + + nvalues = 1 + match = true + if !discard { + *(*byte)(unsafe.Pointer(arg)) = c + arg++ + } + } + if match { + switch { + case width == 0: + r.UnreadByte() + fallthrough + default: + if !discard { + *(*byte)(unsafe.Pointer(arg)) = 0 + } + } + } case 'c': // Matches a sequence of characters whose length is specified by the maximum // field width (default 1); the next pointer must be a pointer to char, and @@ -370,7 +427,69 @@ flags: // hyphen". The string ends with the appearance of a character not in the // (or, with a circumflex, in) set or when the field width runs out. format++ - panic(todo("")) + var re0 []byte + bracket: + for i := 0; ; i++ { + c := *(*byte)(unsafe.Pointer(format)) + format++ + if c == ']' && i != 0 { + break bracket + } + + re0 = append(re0, c) + } + set := map[byte]struct{}{} + re := string(re0) + neg := strings.HasPrefix(re, "^") + if neg { + re = re[1:] + } + for len(re) != 0 { + switch { + case len(re) >= 3 && re[1] == '-': + for c := re[0]; c <= re[2]; c++ { + set[c] = struct{}{} + } + re = re[3:] + default: + set[c] = struct{}{} + re = re[1:] + } + } + var arg uintptr + if !discard { + arg = VaUintptr(args) + } + for ; width != 0; width-- { + c, err := r.ReadByte() + if err != nil { + if err == io.EOF { + return format, nvalues, match + } + + return format, -1, match + } + + if _, ok := set[c]; ok == !neg { + match = true + nvalues = 1 + if !discard { + *(*byte)(unsafe.Pointer(arg)) = c + arg++ + } + } + } + if match { + switch { + case width == 0: + r.UnreadByte() + fallthrough + default: + if !discard { + *(*byte)(unsafe.Pointer(arg)) = 0 + } + } + } case 'p': // Matches a pointer value (as printed by %p in printf(3); the next pointer // must be a pointer to a pointer to void. @@ -378,21 +497,17 @@ flags: skipReaderWhiteSpace(r) c, err := r.ReadByte() if err != nil { - panic(todo("")) - } - - if c != '0' { - r.UnreadByte() - panic(todo("")) + panic(todo("", err)) } - if c, err = r.ReadByte(); err != nil { - panic(todo("")) - } + if c == '0' { + if c, err = r.ReadByte(); err != nil { + panic(todo("", err)) + } - if c != 'x' && c != 'X' { - r.UnreadByte() - panic(todo("")) + if c != 'x' && c != 'X' { + r.UnreadByte() + } } var digit, n uint64 @@ -429,8 +544,10 @@ flags: break } - arg := VaUintptr(args) - *(*uintptr)(unsafe.Pointer(arg)) = uintptr(n) + if !discard { + arg := VaUintptr(args) + *(*uintptr)(unsafe.Pointer(arg)) = uintptr(n) + } nvalues = 1 case 'n': // Nothing is expected; instead, the number of characters consumed thus far |