summaryrefslogtreecommitdiff
path: root/stdlib/scanf.ml
diff options
context:
space:
mode:
authorJun FURUSE / 古瀬 淳 <jun.furuse@gmail.com>2004-06-18 05:04:14 +0000
committerJun FURUSE / 古瀬 淳 <jun.furuse@gmail.com>2004-06-18 05:04:14 +0000
commit5e1bf20850aaa9b1ceb86a971848609ee9e84c47 (patch)
treef3a6e5b5c38263fe527e6275ff95425f12637226 /stdlib/scanf.ml
parent8ec769214e067da9ee8b33d05f4ef275e9269dd5 (diff)
downloadocaml-gcaml.tar.gz
port to the latest ocaml (2004/06/18)gcaml
git-svn-id: http://caml.inria.fr/svn/ocaml/branches/gcaml@6419 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
Diffstat (limited to 'stdlib/scanf.ml')
-rw-r--r--stdlib/scanf.ml109
1 files changed, 72 insertions, 37 deletions
diff --git a/stdlib/scanf.ml b/stdlib/scanf.ml
index 7413e21493..78adcc706a 100644
--- a/stdlib/scanf.ml
+++ b/stdlib/scanf.ml
@@ -115,8 +115,9 @@ type scanbuf = {
file_name : file_name;
};;
-(* Reads a new character from input buffer, sets the end of file
- condition if necessary. *)
+(* Reads a new character from input buffer. Next_char never fails,
+ even in case of end of input: it then simply sets the end of file
+ condition. *)
let next_char ib =
try
let c = ib.get_next_char () in
@@ -264,8 +265,9 @@ let check_char_in range ib =
(* Checking that [c] is indeed in the input, then skip it. *)
let check_char ib c =
let ci = Scanning.checked_peek_char ib in
- if ci == c then Scanning.next_char ib else
- bad_input (Printf.sprintf "looking for %C, found %C" c ci);;
+ if ci != c
+ then bad_input (Printf.sprintf "looking for %C, found %C" c ci)
+ else Scanning.next_char ib;;
(* Extracting tokens from ouput token buffer. *)
@@ -315,11 +317,20 @@ let token_int64 conv ib = int64_of_string (token_int_literal conv ib);;
(* Scanning numbers. *)
-(* The decimal case is optimized. *)
+(* Digits scanning functions suppose that one character has been
+ checked and is available, since they return at end of file with the
+ currently found token selected. The digits scanning functions scan
+ a possibly empty sequence of digits, (hence a successful scanning
+ from one of those functions does not imply that the token is a
+ well-formed number: to get a true number, it is mandatory to check
+ that at least one digit is available before calling a digit
+ scanning function). *)
+
+(* The decimal case is treated especially for optimization purposes. *)
let scan_decimal_digits max ib =
let rec loop inside max =
if max = 0 || Scanning.eof ib then max else
- match Scanning.checked_peek_char ib with
+ match Scanning.cautious_peek_char ib with
| '0' .. '9' as c ->
let max = Scanning.store_char ib c max in
loop true max
@@ -329,11 +340,12 @@ let scan_decimal_digits max ib =
| c -> max in
loop false max;;
-(* Other cases uses a predicate argument to scan_digits. *)
+(* To scan numbers from other bases, we use a predicate argument to
+ scan_digits. *)
let scan_digits digitp max ib =
let rec loop inside max =
if max = 0 || Scanning.eof ib then max else
- match Scanning.checked_peek_char ib with
+ match Scanning.cautious_peek_char ib with
| c when digitp c ->
let max = Scanning.store_char ib c max in
loop true max
@@ -343,28 +355,41 @@ let scan_digits digitp max ib =
| _ -> max in
loop false max;;
-let scan_binary_digits =
- let is_binary_digit = function
+let scan_digits_plus digitp max ib =
+ let c = Scanning.checked_peek_char ib in
+ if digitp c then
+ let max = Scanning.store_char ib c max in
+ scan_digits digitp max ib
+ else bad_input_char c;;
+
+let is_binary_digit = function
| '0' .. '1' -> true
- | _ -> false in
- scan_digits is_binary_digit;;
+ | _ -> false;;
-let scan_octal_digits =
- let is_octal_digit = function
+let scan_binary_digits = scan_digits is_binary_digit;;
+let scan_binary_int = scan_digits_plus is_binary_digit;;
+
+let is_octal_digit = function
| '0' .. '7' -> true
- | _ -> false in
- scan_digits is_octal_digit;;
+ | _ -> false;;
+
+let scan_octal_digits = scan_digits is_octal_digit;;
+let scan_octal_int = scan_digits_plus is_octal_digit;;
-let scan_hexadecimal_digits =
- let is_hexa_digit = function
+let is_hexa_digit = function
| '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' -> true
- | _ -> false in
- scan_digits is_hexa_digit;;
+ | _ -> false;;
+
+let scan_hexadecimal_digits = scan_digits is_hexa_digit;;
+let scan_hexadecimal_int = scan_digits_plus is_hexa_digit;;
-(* Decimal integers. *)
+(* Scan a decimal integer. *)
let scan_unsigned_decimal_int max ib =
- if max = 0 || Scanning.eof ib then bad_input "decimal digit" else
- scan_decimal_digits max ib;;
+ match Scanning.checked_peek_char ib with
+ | '0' .. '9' as c ->
+ let max = Scanning.store_char ib c max in
+ scan_decimal_digits max ib
+ | c -> bad_input_char c;;
let scan_sign max ib =
let c = Scanning.checked_peek_char ib in
@@ -392,28 +417,27 @@ let scan_unsigned_int max ib =
| 'o' -> scan_octal_digits (Scanning.store_char ib c max) ib
| 'b' -> scan_binary_digits (Scanning.store_char ib c max) ib
| c -> scan_decimal_digits max ib end
- | c -> scan_decimal_digits max ib;;
+ | c -> scan_unsigned_decimal_int max ib;;
let scan_optionally_signed_int max ib =
let max = scan_sign max ib in
- if max = 0 || Scanning.eof ib then bad_input "bad int" else
scan_unsigned_int max ib;;
-let scan_int conv max ib =
+let scan_int_conv conv max ib =
match conv with
- | 'b' -> scan_binary_digits max ib
+ | 'b' -> scan_binary_int max ib
| 'd' -> scan_optionally_signed_decimal_int max ib
| 'i' -> scan_optionally_signed_int max ib
- | 'o' -> scan_octal_digits max ib
+ | 'o' -> scan_octal_int max ib
| 'u' -> scan_unsigned_decimal_int max ib
- | 'x' | 'X' -> scan_hexadecimal_digits max ib
+ | 'x' | 'X' -> scan_hexadecimal_int max ib
| c -> assert false;;
(* Scanning floating point numbers. *)
(* Fractional part is optional and can be reduced to 0 digits. *)
let scan_frac_part max ib =
if max = 0 || Scanning.eof ib then max else
- scan_unsigned_decimal_int max ib;;
+ scan_decimal_digits max ib;;
(* Exp part is optional and can be reduced to 0 digits. *)
let scan_exp_part max ib =
@@ -424,8 +448,17 @@ let scan_exp_part max ib =
scan_optionally_signed_decimal_int (Scanning.store_char ib c max) ib
| _ -> max;;
+(* An optional sign followed by a possibly empty sequence of decimal digits. *)
+let scan_optionally_signed_decimal_digits max ib =
+ let max = scan_sign max ib in
+ scan_decimal_digits max ib;;
+
+(* Scan the integer part of a floating point number, (not using the
+ Caml lexical convention since the integer part can be empty). *)
+let scan_int_part = scan_optionally_signed_decimal_digits;;
+
let scan_float max ib =
- let max = scan_optionally_signed_decimal_int max ib in
+ let max = scan_int_part max ib in
if max = 0 || Scanning.eof ib then max else
let c = Scanning.peek_char ib in
match c with
@@ -448,7 +481,7 @@ let scan_Float max ib =
scan_exp_part max ib
| c -> bad_float ();;
-(* Scan a regular string: it stops with a space or one of the
+(* Scan a regular string: stops when encountering a space or one of the
characters in stp. It also stops when the maximum number of
characters has been read.*)
let scan_string stp max ib =
@@ -630,7 +663,7 @@ let make_bv bit set =
if i <= lim then
match set.[i] with
| '-' when rp ->
- (* if i = 0 then rp is false (since the initial call is loop false 0)
+ (* if i = 0 then rp is false (since the initial call is loop bit false 0)
hence i >= 1 and the following is safe. *)
let c1 = set.[i - 1] in
let i = i + 1 in
@@ -665,6 +698,7 @@ let make_setp stp char_set =
(fun c -> if c == p1 || c == p2 then 1 else 0)
| 3 ->
let p1 = set.[0] and p2 = set.[1] and p3 = set.[2] in
+ if p2 = '-' then make_pred 1 set stp else
(fun c -> if c == p1 || c == p2 || c == p3 then 1 else 0)
| n -> make_pred 1 set stp
end
@@ -679,6 +713,7 @@ let make_setp stp char_set =
(fun c -> if c != p1 && c != p2 then 1 else 0)
| 3 ->
let p1 = set.[0] and p2 = set.[1] and p3 = set.[2] in
+ if p2 = '-' then make_pred 0 set stp else
(fun c -> if c != p1 && c != p2 && c != p3 then 1 else 0)
| n -> make_pred 0 set stp
end;;
@@ -751,14 +786,14 @@ let scan_chars_in_char_set stp char_set max ib =
| 0 -> loop (fun c -> 0) max
| 1 -> loop_pos1 set.[0] max
| 2 -> loop_pos2 set.[0] set.[1] max
- | 3 -> loop_pos3 set.[0] set.[1] set.[2] max
+ | 3 when set.[1] != '-' -> loop_pos3 set.[0] set.[1] set.[2] max
| n -> loop (find_setp stp char_set) max end
| Neg_set set ->
begin match String.length set with
| 0 -> loop (fun c -> 1) max
| 1 -> loop_neg1 set.[0] max
| 2 -> loop_neg2 set.[0] set.[1] max
- | 3 -> loop_neg3 set.[0] set.[1] set.[2] max
+ | 3 when set.[1] != '-' -> loop_neg3 set.[0] set.[1] set.[2] max
| n -> loop (find_setp stp char_set) max end in
if stp != [] then check_char_in stp ib;
max;;
@@ -834,7 +869,7 @@ let kscanf ib ef fmt f =
if conv = 'c' then scan_char max ib else scan_Char max ib in
scan_fmt (stack f (token_char ib)) (i + 1)
| 'd' | 'i' | 'o' | 'u' | 'x' | 'X' as conv ->
- let x = scan_int conv max ib in
+ let x = scan_int_conv conv max ib in
scan_fmt (stack f (token_int conv ib)) (i + 1)
| 'f' | 'g' | 'G' | 'e' | 'E' ->
let x = scan_float max ib in
@@ -862,7 +897,7 @@ let kscanf ib ef fmt f =
if i > lim then scan_fmt (stack f (get_count t ib)) i else begin
match fmt.[i] with
| 'd' | 'i' | 'o' | 'u' | 'x' | 'X' as conv ->
- let x = scan_int conv max ib in
+ let x = scan_int_conv conv max ib in
begin match t with
| 'l' -> scan_fmt (stack f (token_int32 conv ib)) (i + 1)
| 'L' -> scan_fmt (stack f (token_int64 conv ib)) (i + 1)