| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  |  | // 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. | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-17 17:10:51 +01:00
										 |  |  |  | //go:build !(linux && (amd64 || loong64)) | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  |  | package libc // import "modernc.org/libc" | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2024-03-04 09:42:11 +00:00
										 |  |  |  | 	"io" | 
					
						
							|  |  |  |  | 	"strconv" | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  |  | 	"unsafe" | 
					
						
							|  |  |  |  | ) | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | // The format string consists of a sequence of directives which describe how to | 
					
						
							|  |  |  |  | // process the sequence of input characters.  If processing of a directive | 
					
						
							|  |  |  |  | // fails, no further input  is  read,  and scanf()  returns.   A "failure" can | 
					
						
							|  |  |  |  | // be either of the following: input failure, meaning that input characters | 
					
						
							|  |  |  |  | // were unavailable, or matching failure, meaning that the input was | 
					
						
							|  |  |  |  | // inappropriate. | 
					
						
							| 
									
										
										
										
											2024-03-04 09:42:11 +00:00
										 |  |  |  | func scanf(r io.ByteScanner, format, args uintptr) (nvalues int32) { | 
					
						
							| 
									
										
										
										
											2022-08-15 12:35:05 +02:00
										 |  |  |  | 	// var src []byte //TODO- | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  |  | 	var ok bool | 
					
						
							|  |  |  |  | out: | 
					
						
							|  |  |  |  | 	for { | 
					
						
							|  |  |  |  | 		c := *(*byte)(unsafe.Pointer(format)) | 
					
						
							| 
									
										
										
										
											2022-08-15 12:35:05 +02:00
										 |  |  |  | 		// src = append(src, c) //TODO- | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  |  | 		switch c { | 
					
						
							|  |  |  |  | 		case '%': | 
					
						
							|  |  |  |  | 			var n int | 
					
						
							|  |  |  |  | 			var match bool | 
					
						
							|  |  |  |  | 			format, n, match = scanfConversion(r, format, &args) | 
					
						
							|  |  |  |  | 			if !match { | 
					
						
							|  |  |  |  | 				break out | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			nvalues += int32(n) | 
					
						
							|  |  |  |  | 			ok = true | 
					
						
							|  |  |  |  | 		case 0: | 
					
						
							|  |  |  |  | 			break out | 
					
						
							|  |  |  |  | 		case ' ', '\t', '\n', '\r', '\v', '\f': | 
					
						
							|  |  |  |  | 			format = skipWhiteSpace(format) | 
					
						
							|  |  |  |  | 			ok = true | 
					
						
							|  |  |  |  | 		next: | 
					
						
							|  |  |  |  | 			for { | 
					
						
							|  |  |  |  | 				c, err := r.ReadByte() | 
					
						
							|  |  |  |  | 				if err != nil { | 
					
						
							|  |  |  |  | 					break out | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				switch c { | 
					
						
							|  |  |  |  | 				case ' ', '\t', '\n', '\r', '\v', '\f': | 
					
						
							|  |  |  |  | 					// nop | 
					
						
							|  |  |  |  | 				default: | 
					
						
							|  |  |  |  | 					r.UnreadByte() | 
					
						
							|  |  |  |  | 					break next | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		default: | 
					
						
							|  |  |  |  | 			c2, err := r.ReadByte() | 
					
						
							|  |  |  |  | 			if err != nil { | 
					
						
							|  |  |  |  | 				break out | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if c2 != c { | 
					
						
							|  |  |  |  | 				r.UnreadByte() | 
					
						
							|  |  |  |  | 				break out | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			format++ | 
					
						
							|  |  |  |  | 			ok = true | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if ok { | 
					
						
							|  |  |  |  | 		return nvalues | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return -1 // stdio.EOF but not defined for windows | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-04 09:42:11 +00:00
										 |  |  |  | func scanfConversion(r io.ByteScanner, format uintptr, args *uintptr) (_ uintptr, nvalues int, match bool) { | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  |  | 	format++ // '%' | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// Each conversion specification in format begins with either the character '%' | 
					
						
							|  |  |  |  | 	// or the character sequence "%n$" (see below for the distinction) followed by: | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	mod := 0 | 
					
						
							|  |  |  |  | 	width := -1 | 
					
						
							|  |  |  |  | flags: | 
					
						
							|  |  |  |  | 	for { | 
					
						
							|  |  |  |  | 		switch c := *(*byte)(unsafe.Pointer(format)); c { | 
					
						
							|  |  |  |  | 		case '*': | 
					
						
							|  |  |  |  | 			// An  optional '*' assignment-suppression character: scanf() reads input as | 
					
						
							|  |  |  |  | 			// directed by the conversion specification, but discards the input.  No | 
					
						
							|  |  |  |  | 			// corresponding pointer argument is re‐ quired, and this specification is not | 
					
						
							|  |  |  |  | 			// included in the count of successful assignments returned by scanf(). | 
					
						
							|  |  |  |  | 			format++ | 
					
						
							|  |  |  |  | 			panic(todo("")) | 
					
						
							|  |  |  |  | 		case '\'': | 
					
						
							|  |  |  |  | 			// For decimal conversions, an optional quote character (').  This specifies | 
					
						
							|  |  |  |  | 			// that the input number may include thousands' separators as defined by the | 
					
						
							|  |  |  |  | 			// LC_NUMERIC category of  the  current locale.  (See setlocale(3).)  The quote | 
					
						
							|  |  |  |  | 			// character may precede or follow the '*' assignment-suppression character. | 
					
						
							|  |  |  |  | 			format++ | 
					
						
							|  |  |  |  | 			panic(todo("")) | 
					
						
							|  |  |  |  | 		case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': | 
					
						
							|  |  |  |  | 			// An  optional  decimal  integer  which  specifies  the maximum field width. | 
					
						
							|  |  |  |  | 			// Reading of characters stops either when this maximum is reached or when a | 
					
						
							|  |  |  |  | 			// nonmatching character is found, whichever happens first.  Most conversions | 
					
						
							|  |  |  |  | 			// discard initial white space characters (the exceptions are noted below), and | 
					
						
							|  |  |  |  | 			// these discarded characters don't  count  toward  the  maximum field width. | 
					
						
							|  |  |  |  | 			// String input conversions store a terminating null byte ('\0') to mark the | 
					
						
							|  |  |  |  | 			// end of the input; the maximum field width does not include this terminator. | 
					
						
							|  |  |  |  | 			width = 0 | 
					
						
							|  |  |  |  | 		num: | 
					
						
							|  |  |  |  | 			for { | 
					
						
							|  |  |  |  | 				var digit int | 
					
						
							|  |  |  |  | 				switch c := *(*byte)(unsafe.Pointer(format)); { | 
					
						
							|  |  |  |  | 				default: | 
					
						
							|  |  |  |  | 					break num | 
					
						
							|  |  |  |  | 				case c >= '0' && c <= '9': | 
					
						
							|  |  |  |  | 					format++ | 
					
						
							|  |  |  |  | 					digit = int(c) - '0' | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 				width0 := width | 
					
						
							|  |  |  |  | 				width = 10*width + digit | 
					
						
							|  |  |  |  | 				if width < width0 { | 
					
						
							|  |  |  |  | 					panic(todo("")) | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		case 'h', 'j', 'l', 'L', 'q', 't', 'z': | 
					
						
							|  |  |  |  | 			format, mod = parseLengthModifier(format) | 
					
						
							|  |  |  |  | 		default: | 
					
						
							|  |  |  |  | 			break flags | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	// A conversion specifier that specifies the type of input conversion to be | 
					
						
							|  |  |  |  | 	// performed. | 
					
						
							|  |  |  |  | 	switch c := *(*byte)(unsafe.Pointer(format)); c { | 
					
						
							|  |  |  |  | 	case '%': | 
					
						
							|  |  |  |  | 		// Matches a literal '%'.  That is, %% in the format string matches a single | 
					
						
							|  |  |  |  | 		// input '%' character.  No conversion is done (but initial white space | 
					
						
							|  |  |  |  | 		// characters are discarded), and assign‐ ment does not occur. | 
					
						
							|  |  |  |  | 		format++ | 
					
						
							|  |  |  |  | 		panic(todo("")) | 
					
						
							|  |  |  |  | 	case 'd': | 
					
						
							|  |  |  |  | 		// Matches an optionally signed decimal integer; the next pointer must be a | 
					
						
							|  |  |  |  | 		// pointer to int. | 
					
						
							|  |  |  |  | 		format++ | 
					
						
							|  |  |  |  | 		skipReaderWhiteSpace(r) | 
					
						
							|  |  |  |  | 		var digit, n uint64 | 
					
						
							|  |  |  |  | 		allowSign := true | 
					
						
							|  |  |  |  | 		neg := false | 
					
						
							|  |  |  |  | 	dec: | 
					
						
							|  |  |  |  | 		for ; width != 0; width-- { | 
					
						
							|  |  |  |  | 			c, err := r.ReadByte() | 
					
						
							|  |  |  |  | 			if err != nil { | 
					
						
							|  |  |  |  | 				if match { | 
					
						
							|  |  |  |  | 					break dec | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-04 09:42:11 +00:00
										 |  |  |  | 				return 0, 0, false | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if allowSign { | 
					
						
							|  |  |  |  | 				switch c { | 
					
						
							|  |  |  |  | 				case '-': | 
					
						
							|  |  |  |  | 					allowSign = false | 
					
						
							|  |  |  |  | 					neg = true | 
					
						
							|  |  |  |  | 					continue | 
					
						
							|  |  |  |  | 				case '+': | 
					
						
							|  |  |  |  | 					allowSign = false | 
					
						
							|  |  |  |  | 					continue | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			switch { | 
					
						
							|  |  |  |  | 			case c >= '0' && c <= '9': | 
					
						
							|  |  |  |  | 				digit = uint64(c) - '0' | 
					
						
							|  |  |  |  | 			default: | 
					
						
							|  |  |  |  | 				r.UnreadByte() | 
					
						
							|  |  |  |  | 				break dec | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			match = true | 
					
						
							|  |  |  |  | 			n0 := n | 
					
						
							|  |  |  |  | 			n = n*10 + digit | 
					
						
							|  |  |  |  | 			if n < n0 { | 
					
						
							|  |  |  |  | 				panic(todo("")) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		if !match { | 
					
						
							|  |  |  |  | 			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("")) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		nvalues = 1 | 
					
						
							|  |  |  |  | 	case 'D': | 
					
						
							|  |  |  |  | 		// Equivalent  to  ld;  this  exists  only for backward compatibility.  (Note: | 
					
						
							|  |  |  |  | 		// thus only in libc4.  In libc5 and glibc the %D is silently ignored, causing | 
					
						
							|  |  |  |  | 		// old programs to fail mysteriously.) | 
					
						
							|  |  |  |  | 		format++ | 
					
						
							|  |  |  |  | 		panic(todo("")) | 
					
						
							|  |  |  |  | 	case 'i': | 
					
						
							|  |  |  |  | 		// Matches an optionally signed integer; the next pointer must be a pointer to | 
					
						
							|  |  |  |  | 		// int.  The integer is read in base 16 if it begins with 0x or 0X, in base 8 | 
					
						
							|  |  |  |  | 		// if it begins with  0,  and  in base 10 otherwise.  Only characters that | 
					
						
							|  |  |  |  | 		// correspond to the base are used. | 
					
						
							|  |  |  |  | 		format++ | 
					
						
							|  |  |  |  | 		panic(todo("")) | 
					
						
							|  |  |  |  | 	case 'o': | 
					
						
							|  |  |  |  | 		// Matches an unsigned octal integer; the next pointer must be a pointer to | 
					
						
							|  |  |  |  | 		// unsigned int. | 
					
						
							|  |  |  |  | 		format++ | 
					
						
							|  |  |  |  | 		panic(todo("")) | 
					
						
							|  |  |  |  | 	case 'u': | 
					
						
							|  |  |  |  | 		// Matches an unsigned decimal integer; the next pointer must be a pointer to | 
					
						
							|  |  |  |  | 		// unsigned int. | 
					
						
							|  |  |  |  | 		format++ | 
					
						
							|  |  |  |  | 		panic(todo("")) | 
					
						
							|  |  |  |  | 	case 'x', 'X': | 
					
						
							|  |  |  |  | 		// Matches an unsigned hexadecimal integer; the next pointer must be a pointer | 
					
						
							|  |  |  |  | 		// to unsigned int. | 
					
						
							|  |  |  |  | 		format++ | 
					
						
							|  |  |  |  | 		skipReaderWhiteSpace(r) | 
					
						
							|  |  |  |  | 		var digit, n uint64 | 
					
						
							|  |  |  |  | 		allowPrefix := true | 
					
						
							|  |  |  |  | 		var b []byte | 
					
						
							|  |  |  |  | 	hex: | 
					
						
							|  |  |  |  | 		for ; width != 0; width-- { | 
					
						
							|  |  |  |  | 			c, err := r.ReadByte() | 
					
						
							|  |  |  |  | 			if err != nil { | 
					
						
							|  |  |  |  | 				if match { | 
					
						
							|  |  |  |  | 					break hex | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				panic(todo("", err)) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			if allowPrefix { | 
					
						
							|  |  |  |  | 				if len(b) == 1 && b[0] == '0' && (c == 'x' || c == 'X') { | 
					
						
							|  |  |  |  | 					allowPrefix = false | 
					
						
							|  |  |  |  | 					match = false | 
					
						
							|  |  |  |  | 					b = nil | 
					
						
							|  |  |  |  | 					continue | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				b = append(b, c) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			switch { | 
					
						
							|  |  |  |  | 			case c >= '0' && c <= '9': | 
					
						
							|  |  |  |  | 				digit = uint64(c) - '0' | 
					
						
							|  |  |  |  | 			case c >= 'a' && c <= 'f': | 
					
						
							|  |  |  |  | 				digit = uint64(c) - 'a' + 10 | 
					
						
							|  |  |  |  | 			case c >= 'A' && c <= 'F': | 
					
						
							|  |  |  |  | 				digit = uint64(c) - 'A' + 10 | 
					
						
							|  |  |  |  | 			default: | 
					
						
							|  |  |  |  | 				r.UnreadByte() | 
					
						
							|  |  |  |  | 				break hex | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			match = true | 
					
						
							|  |  |  |  | 			n0 := n | 
					
						
							|  |  |  |  | 			n = n<<4 + digit | 
					
						
							|  |  |  |  | 			if n < n0 { | 
					
						
							|  |  |  |  | 				panic(todo("")) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		if !match { | 
					
						
							|  |  |  |  | 			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("")) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		nvalues = 1 | 
					
						
							|  |  |  |  | 	case 'f', 'e', 'g', 'E', 'a': | 
					
						
							|  |  |  |  | 		// Matches an optionally signed floating-point number; the next pointer must be | 
					
						
							|  |  |  |  | 		// a pointer to float. | 
					
						
							|  |  |  |  | 		format++ | 
					
						
							| 
									
										
										
										
											2024-03-04 09:42:11 +00:00
										 |  |  |  | 		skipReaderWhiteSpace(r) | 
					
						
							|  |  |  |  | 		seq := fpLiteral(r) | 
					
						
							|  |  |  |  | 		if len(seq) == 0 { | 
					
						
							|  |  |  |  | 			return 0, 0, false | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		var neg bool | 
					
						
							|  |  |  |  | 		switch seq[0] { | 
					
						
							|  |  |  |  | 		case '+': | 
					
						
							|  |  |  |  | 			seq = seq[1:] | 
					
						
							|  |  |  |  | 		case '-': | 
					
						
							|  |  |  |  | 			neg = true | 
					
						
							|  |  |  |  | 			seq = seq[1:] | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		n, err := strconv.ParseFloat(string(seq), 64) | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			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)) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		return format, 1, true | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  |  | 	case 's': | 
					
						
							|  |  |  |  | 		// Matches  a  sequence of non-white-space characters; the next pointer must be | 
					
						
							|  |  |  |  | 		// a pointer to the initial element of a character array that is long enough to | 
					
						
							|  |  |  |  | 		// 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("")) | 
					
						
							|  |  |  |  | 	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 | 
					
						
							|  |  |  |  | 		// there must be enough room for  all the characters (no terminating null byte | 
					
						
							|  |  |  |  | 		// is added).  The usual skip of leading white space is suppressed.  To skip | 
					
						
							|  |  |  |  | 		// white space first, use an explicit space in the format. | 
					
						
							|  |  |  |  | 		format++ | 
					
						
							|  |  |  |  | 		panic(todo("")) | 
					
						
							|  |  |  |  | 	case '[': | 
					
						
							|  |  |  |  | 		// Matches  a nonempty sequence of characters from the specified set of | 
					
						
							|  |  |  |  | 		// accepted characters; the next pointer must be a pointer to char, and there | 
					
						
							|  |  |  |  | 		// must be enough room for all the char‐ acters in the string, plus a | 
					
						
							|  |  |  |  | 		// terminating null byte.  The usual skip of leading white space is suppressed. | 
					
						
							|  |  |  |  | 		// The string is to be made up of characters in (or not in) a particular set; | 
					
						
							|  |  |  |  | 		// the  set  is defined by the characters between the open bracket [ character | 
					
						
							|  |  |  |  | 		// and a close bracket ] character.  The set excludes those characters if the | 
					
						
							|  |  |  |  | 		// first character after the open bracket is a circumflex (^).  To include a | 
					
						
							|  |  |  |  | 		// close bracket in the set, make it the first character after the open bracket | 
					
						
							|  |  |  |  | 		// or the circumflex; any other position will end the set.   The hyphen | 
					
						
							|  |  |  |  | 		// character - is also special; when placed between two other characters, it | 
					
						
							|  |  |  |  | 		// adds all intervening characters to the set.  To include a hyphen, make it | 
					
						
							|  |  |  |  | 		// the last character before the final close bracket.  For instance, [^]0-9-] | 
					
						
							|  |  |  |  | 		// means the set "everything except close bracket, zero through nine, and | 
					
						
							|  |  |  |  | 		// 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("")) | 
					
						
							|  |  |  |  | 	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. | 
					
						
							|  |  |  |  | 		format++ | 
					
						
							|  |  |  |  | 		skipReaderWhiteSpace(r) | 
					
						
							|  |  |  |  | 		c, err := r.ReadByte() | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			panic(todo("")) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if c != '0' { | 
					
						
							|  |  |  |  | 			r.UnreadByte() | 
					
						
							|  |  |  |  | 			panic(todo("")) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if c, err = r.ReadByte(); err != nil { | 
					
						
							|  |  |  |  | 			panic(todo("")) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		if c != 'x' && c != 'X' { | 
					
						
							|  |  |  |  | 			r.UnreadByte() | 
					
						
							|  |  |  |  | 			panic(todo("")) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		var digit, n uint64 | 
					
						
							|  |  |  |  | 	ptr: | 
					
						
							|  |  |  |  | 		for ; width != 0; width-- { | 
					
						
							|  |  |  |  | 			c, err := r.ReadByte() | 
					
						
							|  |  |  |  | 			if err != nil { | 
					
						
							|  |  |  |  | 				if match { | 
					
						
							|  |  |  |  | 					break ptr | 
					
						
							|  |  |  |  | 				} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 				panic(todo("")) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 			switch { | 
					
						
							|  |  |  |  | 			case c >= '0' && c <= '9': | 
					
						
							|  |  |  |  | 				digit = uint64(c) - '0' | 
					
						
							|  |  |  |  | 			case c >= 'a' && c <= 'f': | 
					
						
							|  |  |  |  | 				digit = uint64(c) - 'a' + 10 | 
					
						
							|  |  |  |  | 			case c >= 'A' && c <= 'F': | 
					
						
							|  |  |  |  | 				digit = uint64(c) - 'A' + 10 | 
					
						
							|  |  |  |  | 			default: | 
					
						
							|  |  |  |  | 				r.UnreadByte() | 
					
						
							|  |  |  |  | 				break ptr | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 			match = true | 
					
						
							|  |  |  |  | 			n0 := n | 
					
						
							|  |  |  |  | 			n = n<<4 + digit | 
					
						
							|  |  |  |  | 			if n < n0 { | 
					
						
							|  |  |  |  | 				panic(todo("")) | 
					
						
							|  |  |  |  | 			} | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		if !match { | 
					
						
							|  |  |  |  | 			break | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		arg := VaUintptr(args) | 
					
						
							|  |  |  |  | 		*(*uintptr)(unsafe.Pointer(arg)) = uintptr(n) | 
					
						
							|  |  |  |  | 		nvalues = 1 | 
					
						
							|  |  |  |  | 	case 'n': | 
					
						
							|  |  |  |  | 		// Nothing is expected; instead, the number of characters consumed thus far | 
					
						
							|  |  |  |  | 		// from the input is stored through the next pointer, which must be a pointer | 
					
						
							|  |  |  |  | 		// to int.  This is not a conversion and does not increase the count returned | 
					
						
							|  |  |  |  | 		// by the function.  The assignment can be suppressed with the * | 
					
						
							|  |  |  |  | 		// assignment-suppression character, but the effect on the return value is | 
					
						
							|  |  |  |  | 		// undefined.  Therefore %*n conversions should not be used. | 
					
						
							|  |  |  |  | 		format++ | 
					
						
							|  |  |  |  | 		panic(todo("")) | 
					
						
							|  |  |  |  | 	default: | 
					
						
							|  |  |  |  | 		panic(todo("%#U", c)) | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	return format, nvalues, match | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-03-04 09:42:11 +00:00
										 |  |  |  | func skipReaderWhiteSpace(r io.ByteScanner) error { | 
					
						
							| 
									
										
										
										
											2021-08-29 15:41:41 +01:00
										 |  |  |  | 	for { | 
					
						
							|  |  |  |  | 		c, err := r.ReadByte() | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			return err | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		switch c { | 
					
						
							|  |  |  |  | 		case ' ', '\t', '\n', '\r', '\v', '\f': | 
					
						
							|  |  |  |  | 			// ok | 
					
						
							|  |  |  |  | 		default: | 
					
						
							|  |  |  |  | 			r.UnreadByte() | 
					
						
							|  |  |  |  | 			return nil | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | func skipWhiteSpace(s uintptr) uintptr { | 
					
						
							|  |  |  |  | 	for { | 
					
						
							|  |  |  |  | 		switch c := *(*byte)(unsafe.Pointer(s)); c { | 
					
						
							|  |  |  |  | 		case ' ', '\t', '\n', '\r', '\v', '\f': | 
					
						
							|  |  |  |  | 			s++ | 
					
						
							|  |  |  |  | 		default: | 
					
						
							|  |  |  |  | 			return s | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | } | 
					
						
							| 
									
										
										
										
											2024-03-04 09:42:11 +00:00
										 |  |  |  | 
 | 
					
						
							|  |  |  |  | // [-+]?([0-9]*[.])?[0-9]+([eE][-+]?\d+)? | 
					
						
							|  |  |  |  | func fpLiteral(rd io.ByteScanner) (seq []byte) { | 
					
						
							|  |  |  |  | 	const endOfText = 0x110000 | 
					
						
							|  |  |  |  | 	var pos, width, length int | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	defer func() { | 
					
						
							|  |  |  |  | 		if len(seq) > length { | 
					
						
							|  |  |  |  | 			rd.UnreadByte() | 
					
						
							|  |  |  |  | 			seq = seq[:len(seq)-1] | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	}() | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 	var r rune | 
					
						
							|  |  |  |  | 	step := func(pos int) (rune, int) { | 
					
						
							|  |  |  |  | 		b, err := rd.ReadByte() | 
					
						
							|  |  |  |  | 		if err != nil { | 
					
						
							|  |  |  |  | 			return endOfText, 0 | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 
 | 
					
						
							|  |  |  |  | 		seq = append(seq, b) | 
					
						
							|  |  |  |  | 		return rune(b), 1 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	move := func() { | 
					
						
							|  |  |  |  | 		pos += width | 
					
						
							|  |  |  |  | 		if r != endOfText { | 
					
						
							|  |  |  |  | 			r, width = step(pos + width) | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	accept := func(x rune) bool { | 
					
						
							|  |  |  |  | 		if r == x { | 
					
						
							|  |  |  |  | 			move() | 
					
						
							|  |  |  |  | 			return true | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		return false | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	accept2 := func(x rune) bool { | 
					
						
							|  |  |  |  | 		if r <= x { | 
					
						
							|  |  |  |  | 			move() | 
					
						
							|  |  |  |  | 			return true | 
					
						
							|  |  |  |  | 		} | 
					
						
							|  |  |  |  | 		return false | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	r = endOfText | 
					
						
							|  |  |  |  | 	width = 0 | 
					
						
							|  |  |  |  | 	r, width = step(pos) | 
					
						
							|  |  |  |  | 	if accept('.') { | 
					
						
							|  |  |  |  | 		goto l7 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if accept('+') { | 
					
						
							|  |  |  |  | 		goto l30 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if accept('-') { | 
					
						
							|  |  |  |  | 		goto l30 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if r < '0' { | 
					
						
							|  |  |  |  | 		goto l4out | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if accept2('9') { | 
					
						
							|  |  |  |  | 		goto l35 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | l4out: | 
					
						
							|  |  |  |  | 	return seq | 
					
						
							|  |  |  |  | l7: | 
					
						
							|  |  |  |  | 	if r < '0' { | 
					
						
							|  |  |  |  | 		goto l7out | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if accept2('9') { | 
					
						
							|  |  |  |  | 		goto l10 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | l7out: | 
					
						
							|  |  |  |  | 	return seq | 
					
						
							|  |  |  |  | l10: | 
					
						
							|  |  |  |  | 	length = pos | 
					
						
							|  |  |  |  | 	if accept('E') { | 
					
						
							|  |  |  |  | 		goto l18 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if accept('e') { | 
					
						
							|  |  |  |  | 		goto l18 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if r < '0' { | 
					
						
							|  |  |  |  | 		goto l15out | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if accept2('9') { | 
					
						
							|  |  |  |  | 		goto l10 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | l15out: | 
					
						
							|  |  |  |  | 	return seq | 
					
						
							|  |  |  |  | l18: | 
					
						
							|  |  |  |  | 	if accept('+') { | 
					
						
							|  |  |  |  | 		goto l23 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if accept('-') { | 
					
						
							|  |  |  |  | 		goto l23 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if r < '0' { | 
					
						
							|  |  |  |  | 		goto l20out | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if accept2('9') { | 
					
						
							|  |  |  |  | 		goto l26 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | l20out: | 
					
						
							|  |  |  |  | 	return seq | 
					
						
							|  |  |  |  | l23: | 
					
						
							|  |  |  |  | 	if r < '0' { | 
					
						
							|  |  |  |  | 		goto l23out | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if accept2('9') { | 
					
						
							|  |  |  |  | 		goto l26 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | l23out: | 
					
						
							|  |  |  |  | 	return seq | 
					
						
							|  |  |  |  | l26: | 
					
						
							|  |  |  |  | 	length = pos | 
					
						
							|  |  |  |  | 	if r < '0' { | 
					
						
							|  |  |  |  | 		goto l27out | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if accept2('9') { | 
					
						
							|  |  |  |  | 		goto l26 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | l27out: | 
					
						
							|  |  |  |  | 	return seq | 
					
						
							|  |  |  |  | l30: | 
					
						
							|  |  |  |  | 	if accept('.') { | 
					
						
							|  |  |  |  | 		goto l7 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if r < '0' { | 
					
						
							|  |  |  |  | 		goto l32out | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if accept2('9') { | 
					
						
							|  |  |  |  | 		goto l35 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | l32out: | 
					
						
							|  |  |  |  | 	return seq | 
					
						
							|  |  |  |  | l35: | 
					
						
							|  |  |  |  | 	length = pos | 
					
						
							|  |  |  |  | 	if accept('.') { | 
					
						
							|  |  |  |  | 		goto l7 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if accept('E') { | 
					
						
							|  |  |  |  | 		goto l18 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if accept('e') { | 
					
						
							|  |  |  |  | 		goto l18 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if r < '0' { | 
					
						
							|  |  |  |  | 		goto l42out | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | 	if accept2('9') { | 
					
						
							|  |  |  |  | 		goto l35 | 
					
						
							|  |  |  |  | 	} | 
					
						
							|  |  |  |  | l42out: | 
					
						
							|  |  |  |  | 	return seq | 
					
						
							|  |  |  |  | } |