|D,9~55.5.0+dev0-2025-04-28/%Scanfӱ(Scanning!A@*in_channelB;@@@A@@@@@6../../stdlib/scanf.mlieSSeSb@@@@%Scanf@@A@'scanbufC;@@ A%ScanfJ(Scanning*in_channel@@@|@@@@q||q|@@@@A@A@%stdin%ScanfK(Scanning*in_channel@@@@)}*}@@(B@@)file_nameD;@@3A&stringL@@@@@@@9:@@@@8C@A@'open_in@%ScanfM(Scanning)file_name@@@@@%ScanfN(Scanning*in_channel@@@@@@Z55[5Z@@YD@@+open_in_bin@%ScanfO(Scanning)file_name@@@@@%ScanfP(Scanning*in_channel@@@@@@{  | 6@@zE@@(close_in@%ScanfQ(Scanning*in_channel@@@@@$unitR@@@@@@@@F@@)from_file@%ScanfS(Scanning)file_name@@@@@%ScanfT(Scanning*in_channel@@@@@@@@G@@-from_file_bin@U@@@@@%ScanfV(Scanning*in_channel@@@@@@@@H@@+from_string@W@@@@@%ScanfX(Scanning*in_channel@@@@@@;;;a@@I@@-from_function@@pY@@@@@$charZ@@@@@@@%Scanf[(Scanning*in_channel@@@@@@kkk@@J@@,from_channel@&Stdlib\*in_channel@@@@@%Scanf](Scanning*in_channel@@@@@@67:@@5K@@,end_of_input@%Scanf^(Scanning*in_channel@@@@@$bool_@@@@@@S & &T & K@@RL@@2beginning_of_input@%Scanf`(Scanning*in_channel@@@@@a@@@@@@o  p  @@nM@@-name_of_input @%Scanfb(Scanning*in_channel@@@@@Sc@@@@@@!!!!@@N@@@@c<<"V"Y@O@@@'scanner"E;!a@!b@!c@ !d@@DA@&Stdlibe'format6"F@Ġ%Scanfd(Scanning*in_channel@@@+F@)F@@@@+F@@@@@@@@ @@OO@@@@@@@@""""@@@@P@A@+scanner_opt@%Scanfi(Scanning*in_channel@@@@@%Scanfj'scanner!a@H@Ơ!b@H@Ǡ!c@H@Ƞ!d@H@@@@@@@((((@@S@@*bscanf_opt?@%Scanfk(Scanning*in_channel@@@@@%Scanfl+scanner_opt!a@H@ڠ!b@H@۠!c@H@ܠ!d@H@@@@@@@ +B+B +B+@@T@@&sscanf@@m@@@@@%Scanfn'scanner!a@H@!b@H@!c@H@!d@H@@@@@@@WWWW@@U@@*sscanf_optA@o@@@@@ %Scanfp+scanner_opt!a@H@!b@H@!c@H@!d@H@@@@ @@ @'XX(XXN@@&V@@%scanfB%Scanfq'scanner!a@H@!b@!H@!c@#H@!d@%H@@@@@TXXUXX@@SW@@)scanf_optC%Scanfr+scanner_opt!a@0H@&!b@2H@'!c@4H@(!d@6H@)@@@.@YnYnYnY@@X@@&kscanfD@%Scanfs(Scanning*in_channel@@@7@@I@@%Scanft(Scanning*in_channel@@@8@@=@uu@@@9@@;!d@RH@:@@<@@>@@G%Scanfv'scanner!a@LH@?!b@NH@@!c@PH@A#@@@F@@H@@J@YYZGZc@@Y@@'ksscanfE@w@@@S@@e@@%Scanfx(Scanning*in_channel@@@T@@Y@y@@@U@@W!d@nH@V@@X@@Z@@c%Scanfz'scanner!a@hH@[!b@jH@\!c@lH@]#@@@b@@d@@f@([[)\\@@'Z@@-bscanf_formatF@%Scanf{(Scanning*in_channel@@@o@@@&Stdlib|'format6!a@H@p!b@H@q!c@H@r!d@H@s!e@H@t!f@H@u@@@|@@@@&Stdlib}'format6:4.("@@@@@!g@H@@@@@@@@@@@@ \\ \]!@@[@@-sscanf_formatG@k~@@@@@@&Stdlib'format6!a@H@!b@H@!c@H@!d@H@!e@H@!f@H@@@@@@@@&Stdlib'format6:4.("@@@@@!g@H@@@@@@@@@@@@^b^b^^@@\@@2format_from_stringH@@@@@@@&Stdlib'format6!a@H@Ƞ!b@H@ɠ!c@H@ʠ!d@H@ˠ!e@H@̠!f@H@@@@@@&Stdlib'format62,& @@@@@@@@K_2_2L_W_@@J]@@)unescapedI@%@@@@@*@@@@@@b'``c'``@@a^@@@3:Formatted input functions.@@@@@@@@@@@5unsynchronized_access GUnsynchronized accesses to Scanning.in_channel are a programming error.@A6../../stdlib/scanf.mliA@,Introduction@@B@ $Functional input with format strings@@+The module @@ ' provides formatted input functions or (scanners@!.@ The formatted input functions can read from any kind of input, including strings, files, or anything that can return characters. The more general source of characters is named a 7formatted input channel@% (or 3 scanning buffer@/) and has type 9Scanf.Scanning.in_channelE@ `. The more general formatted input function reads from any scanning buffer and is named &bscanf!.@ H Generally speaking, the formatted input functions have 3 arguments: ;the first argument is a source of characters for the input,@ Othe second argument is a format string that specifies the values to read,@8the third argument is a 1receiver function@ * that is applied to the values read.@@ ; Hence, a typical call to the formatted input function ,Scanf.bscanfD@( is /bscanf ic fmt f(, where:@"ic ( is a source of characters (typically a ; formatted input channel@+ with type IE@"),@@#fmt ] is a format string (the same format strings as those used to print material with module &Printf@@$ or &Format@@"),@@!f h is a function that has as many arguments as the number of values to read in the input according to #fmt!.@@@B@0A simple example@@ #As suggested above, the expression 0bscanf ic "%d" f= reads a decimal integer !n? from the source of characters "ic- and returns #f n!.@2 For instance,@*if we use %stdin> as the source of characters (4Scanf.Scanning.stdinD@ O is the predefined formatted input channel that reads from standard input),@@:if we define the receiver !f$ as /let f x = x + 1!,@@* then may lead to an invalid  E@ + state. Thus, concurrent accesses to E@ 2s must be synchronized (for instance with a 'Mutex.t@@").@A@7Formatted input channel@@/.Scanf.Scanning@A`#+3 $The notion of input channel for the @@ u module: those channels provide all the machinery necessary to read from any source of characters, including a 1Stdlib.in_channel@@ > value. A Scanf.Scanning.in_channel value is also called a :formatted input channel@3 or equivalently a /scanning buffer@.. The type 6Scanf.Scanning.scanbufE@7 below is an alias for 3Scanning.in_channel1. Note that a 3Scanning.in_channel W is not concurrency-safe: concurrent use may produce arbitrary values or exceptions.@@@@$3.12@@@@@@@@@A@@ @@#3 %The type of scanning buffers. A scanning buffer is the source from which a formatted input function gets characters. The scanning buffer holds the current state of the scan, plus a function to get the next char from the input, and a token buffer to store the string matched so far.@ Note: a scanning action may often require to examine one character in advance; when this 'lookahead' character does not belong to the token read, it is stored back in the scanning buffer and becomes the next character yet to be read.@@@@@@@@@@@@@@A@  @@Ґ3 "The standard input notion for the :@@- module. .Scanning.stdin( is the E@ ) formatted input channel attached to ,Stdlib.stdin@@!.@ B Note: in the interactive system, when input is read from ,Stdlib.stdin@@ , the newline character that triggers evaluation is part of the input; thus, the scanning specifications must properly skip this additional newline character (for instance, simply add a $'\n' 1 as the last character of the format string).@@@@$3.12@@@@@@@5@@@@-#8Scanf.Scanning.file_name3 ,A convenient alias to designate a file name.@@@@$4.00@@@@@@@@@A1@-,@@6Scanf.Scanning.open_in36Scanning.open_in fname+ returns a ̐E@ K formatted input channel for bufferized reading in text mode from file %fname!.@/ Note: 'open_in g returns a formatted input channel that efficiently reads characters in large chunks; in contrast, ,from_channel  below returns formatted input channels that must read one character at a time, leading to a much slower scanning rate.@@@@$3.12@@@@@@@P@ R@@@@>:Scanf.Scanning.open_in_bin3:Scanning.open_in_bin fname+ returns a E@ M formatted input channel for bufferized reading in binary mode from file %fname!.@@@@$3.12@@@@@@@P@!Q@@@@=7Scanf.Scanning.close_in3+Closes the 1Stdlib.in_channel@@= associated with the given  E@9 formatted input channel.@@@@$3.12@@@@@@@L@>M@@@@=8Scanf.Scanning.from_file3-An alias for wD@' above.@@@@@@@@@@@@D@SE@@@@1Scanning.beginning_of_input ic 9 tests the beginning of input condition of the given E@9 formatted input channel.@@@@@@@@@@@@>@?@@@@0 i + 1+, then Scanf.sscanf "x = 1" "%s = %i" f) returns !2!.@/ Arguments "r1$ to "rN R are user-defined input functions that read the argument corresponding to the "%r 0 conversions specified in the format string.@0Scanf.bscanf_opt3(Same as HD@., but returns $None= in case of scanning failure.@@@@#5.0@@@@@@@@@@@@rA@9Format string description@@ RThe format string is a character string which contains three types of objects: plain characters, which are simply matched with the characters of the input (with a special case for space and line feed, see +Scanf.space %The space character in format strings@@"),@ nconversion specifications, each of which causes reading and conversion of one argument for the function !f& (see 0Scanf.conversion +Conversion specifications in format strings@@"),@ Iscanning indications to specify boundaries of tokens (see scanning 0Scanf.indication &Scanning indications in format strings@@").@@@B%space0@@ As mentioned above, a plain character in the format string is just matched with the next character of the input; however, two characters are special exceptions to this rule: the space character (#' ' 4 or ASCII code 32) and the line feed character ($'\n' or ASCII code 10). A space does not match a single space character, but any amount of 'whitespace' in the input. More precisely, a space inside the format string matches *any number@ of tab, space, line feed and carriage return characters. Similarly, a line feed character in the format string matches either a single line feed or a carriage return followed by a line feed.@. Matching #any@ u amount of whitespace, a space in the format string also matches no amount of whitespace at all; hence, the call )bscanf ib "Price = %d $" (fun p -> p)6 succeeds and returns !1 B when reading an input with various whitespace in it, such as +Price = 1 $&, 0Price = 1 $*, or even (Price=1$!.@B*conversione@@ )Conversion specifications consist in the !% | character, followed by an optional flag, an optional field width, and followed by one or two conversion characters.@ 6 The conversion characters and their meanings are:@!d .: reads an optionally signed decimal integer (#0-9#+).@!i Q: reads an optionally signed integer (usual input conventions for decimal (#0-98+), hexadecimal (+0x[0-9a-f]+% and +0X[0-9A-F]+*), octal ((0o[0-7]+6), and binary ((0b[0-1]+<) notations are understood).@!u $: reads an unsigned decimal integer.@!x$ or !X ): reads an unsigned hexadecimal integer (,[0-9a-fA-F]+").@!o #: reads an unsigned octal integer (&[0-7]+").@!s v: reads a string argument that spreads as much as possible, until the following bounding condition holds: !a whitespace has been found (see +Scanf.space@"),@ $a scanning indication (see scanning 0Scanf.indication@ ) has been encountered,@ "the end-of-input has been reached.@@ Hence, this conversion always succeeds: it returns an empty string if the bounding condition holds when the scan begins.@!S ~: reads a delimited string argument (delimiters and special escaped characters follow the lexical conventions of OCaml).@!c : reads a single character. To test the current input character without reading it, specify a null field width, i.e. use specification #%0c(. Raise 0Invalid_argument ;, if the field width specification is greater than 1.@!C : reads a single delimited character (delimiters and special escaped characters follow the lexical conventions of OCaml).@!f", !e", !E", !g", !G [: reads an optionally signed floating-point number in decimal notation, in the style 6dddd.ddd e/E+-dd!.@!h", !H Q: reads an optionally signed floating-point number in hexadecimal notation.@!F : reads a floating point number according to the lexical conventions of OCaml (hence the decimal point is mandatory if the exponent part is not mentioned).@!B<: reads a boolean argument ($true$ or %false").@!b Z: reads a boolean argument (for backward compatibility; do not use in new programs).@"ld", "li", "lu", "lx", "lX", "lo+: reads an %int32 R argument to the format specified by the second letter for regular integers.@"nd", "ni", "nu", "nx", "nX", "no*: reads a )nativeint R argument to the format specified by the second letter for regular integers.@"Ld", "Li", "Lu", "Lx", "LX", "Lo+: reads an %int64 R argument to the format specified by the second letter for regular integers.@)[ range ] a: reads characters that matches one of the characters mentioned in the range of characters %range 9 (or not mentioned in it, if the range starts with !^+). Reads a &string q that can be empty, if the next input character does not match the range. The set of characters from "c1$ to "c2= (inclusively) is denoted by %c1-c2/. Hence, &%[0-9] x returns a string representing a decimal number or an empty string if no decimal digit is found; similarly, )%[0-9a-f] returns a string of hexadecimal digits. If a closing bracket appears in a range, it must occur as the first character of the range (or just after the !^ ) in case of range negation); hence #[]]+ matches a !]5 character and $[^]] # matches any character that is not !],. Use "%%% and "%@. to include a !%& or a !@, in a range.@!r &: user-defined reader. Takes the next "ri F formatted input function and applies it to the scanning buffer "ib 5 to read the next argument. The input function "ri must therefore have type 9Scanning.in_channel -> 'a and the argument read has type "'a!.@({ fmt %} : reads a format string argument. The format string read must have the same type as the format string specification #fmt0. For instance, *"%{ %i %}" = reads any format string that can read a value of type #int,; hence, if !s5 is the string 6"fmt:\"number is %u\""', then fmt, i)4 evaluates to -("%4d", 1234) . This behaviour is not mere format substitution, since the conversion returns the format string read as additional argument. If you need pure format substitution, use special flag !_ 6 to discard the extraneous argument: conversion *%_( fmt %)= reads a format string "rf , and then behaves the same as format string "rf-. Hence, if !s5 is the string 0"\"%4d\"1234.00"', then 8Scanf.sscanf s "%_(%i%)"? is simply equivalent to i + 1&, and !s3 is the string '"x = 1"', then ;Scanf.sscanf s "%_s = %i" f) returns !2!.@ The field width is composed of an optional integer literal indicating the maximal width of the token to read. For instance, #%6d 8 reads an integer, having at most 6 decimal digits; #%4f . reads a float with at most 4 characters; and -%8[\000-\255] returns the next 8 characters (or all the characters still available, if fewer than 8 characters are available in the input).@+ Notes:@6as mentioned above, a "%s r conversion always succeeds, even if there is nothing to read in the input: in this case, it simply returns """!.@@ $in addition to the relevant digits, #'_' characters may appear inside numbers (this is reminiscent to the usual OCaml lexical conventions). If stricter scanning is desired, use the range conversion facility instead of the number conversions.@@$the %scanf facility is not intended for heavy duty lexical analysis and parsing. If it appears not expressive enough for your needs, several alternative exists: regular expressions (module #Str@@3), stream parsers, (ocamllex7-generated lexers, )ocamlyacc3-generated parsers.@@@B*indication@@ >Scanning indications appear just after the string conversions "%s) and *%[ range ] O to delimit the end of the token. A scanning indication is introduced by a !@ 1 character, followed by some plain character !c N. It means that the string token should end just before the next matching !c; (which is skipped). If no !c _ character is encountered, the string token spreads as much as possible. For instance, '"%s@\t" N reads a string up to the next tab character or to the end of input. If a !@ ^ character appears anywhere else in the format string, it is treated as a plain character.@* Note:@