summaryrefslogtreecommitdiffstats
path: root/stdlib/camlinternalFormat.ml
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib/camlinternalFormat.ml')
-rw-r--r--stdlib/camlinternalFormat.ml39
1 files changed, 23 insertions, 16 deletions
diff --git a/stdlib/camlinternalFormat.ml b/stdlib/camlinternalFormat.ml
index 4e5e69b3d..e4119b6fd 100644
--- a/stdlib/camlinternalFormat.ml
+++ b/stdlib/camlinternalFormat.ml
@@ -1321,7 +1321,7 @@ let fmt_ebb_of_string str =
if str_ind = end_ind then add_literal lit_start str_ind End_of_format else
match str.[str_ind] with
| '%' ->
- let Fmt_EBB fmt_rest = parse_flags str_ind end_ind in
+ let Fmt_EBB fmt_rest = parse_format str_ind end_ind in
add_literal lit_start str_ind fmt_rest
| '@' ->
let Fmt_EBB fmt_rest = parse_after_at (str_ind + 1) end_ind in
@@ -1329,17 +1329,28 @@ let fmt_ebb_of_string str =
| _ ->
parse_literal lit_start (str_ind + 1) end_ind
- and parse_flags : type e f . int -> int -> (_, _, e, f) fmt_ebb =
- fun pct_ind end_ind ->
- let zero = ref false and minus = ref false and plus = ref false
- and sharp = ref false and space = ref false and ign = ref false in
+ (* Parse a format after '%' *)
+ and parse_format : type e f . int -> int -> (_, _, e, f) fmt_ebb =
+ fun pct_ind end_ind -> parse_ign pct_ind (pct_ind + 1) end_ind
+
+ and parse_ign : type e f . int -> int -> int -> (_, _, e, f) fmt_ebb =
+ fun pct_ind str_ind end_ind ->
+ match str.[str_ind] with
+ | '_' -> parse_flags pct_ind (str_ind+1) end_ind true
+ | _ -> parse_flags pct_ind str_ind end_ind false
+
+ and parse_flags : type e f . int -> int -> int -> bool -> (_, _, e, f) fmt_ebb =
+ fun pct_ind str_ind end_ind ign ->
+ let zero = ref false and minus = ref false
+ and plus = ref false and space = ref false
+ and sharp = ref false in
let set_flag str_ind flag =
- (* in legacy mode, duplicate flags are accepted, except '_' *)
- if !flag && (not legacy_behavior || flag == ign) then
+ (* in legacy mode, duplicate flags are accepted *)
+ if !flag && not legacy_behavior then
failwith_message
"invalid format %S: at character number %d, duplicate flag %C"
str str_ind str.[str_ind];
- flag := true
+ flag := true;
in
let rec read_flags str_ind =
if str_ind = end_ind then unexpected_end_of_format end_ind;
@@ -1349,13 +1360,12 @@ let fmt_ebb_of_string str =
| '+' -> set_flag str_ind plus; read_flags (str_ind + 1)
| '#' -> set_flag str_ind sharp; read_flags (str_ind + 1)
| ' ' -> set_flag str_ind space; read_flags (str_ind + 1)
- | '_' -> set_flag str_ind ign; read_flags (str_ind + 1)
| _ ->
parse_padding pct_ind str_ind end_ind
- !zero !minus !plus !sharp !space !ign
+ !zero !minus !plus !sharp !space ign
end
in
- read_flags (pct_ind + 1)
+ read_flags str_ind
(* Try to read a digital or a '*' padding. *)
and parse_padding : type e f .
@@ -1660,11 +1670,8 @@ let fmt_ebb_of_string str =
(* Check for unused options, and reject them as incompatible.
Such checks need to be disabled in legacy mode, as the legacy
- parser silently ignored incompatible flags. But ignored formats
- are an exception: '%_+3d' was already rejected for example. So
- we enable those checks, even in legacy mode, when 'ign' is
- set. *)
- if not legacy_behavior || ign then begin
+ parser silently ignored incompatible flags. *)
+ if not legacy_behavior then begin
if not !plus_used && plus then
incompatible_flag pct_ind str_ind symb "'+'";
if not !sharp_used && sharp then