Skip to content

Commit b4ccb87

Browse files
author
Damien Doligez
committedJan 11, 2012
PR#5380: copy fix from 3.12 branch
git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@12014 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
1 parent cbcf38a commit b4ccb87

File tree

5 files changed

+287
-245
lines changed

5 files changed

+287
-245
lines changed
 

‎stdlib/printf.ml

+9-5
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ let iter_on_format_args fmt add_conv add_char =
217217
and scan_conv skip i =
218218
if i > lim then incomplete_format fmt else
219219
match Sformat.unsafe_get fmt i with
220-
| '%' | '!' | ',' -> succ i
220+
| '%' | '@' | '!' | ',' -> succ i
221221
| 's' | 'S' | '[' -> add_conv skip i 's'
222222
| 'c' | 'C' -> add_conv skip i 'c'
223223
| 'd' | 'i' |'o' | 'u' | 'x' | 'X' | 'N' -> add_conv skip i 'i'
@@ -505,8 +505,10 @@ let scan_format fmt args n pos cont_s cont_a cont_t cont_f cont_m =
505505

506506
and scan_conv spec n widths i =
507507
match Sformat.unsafe_get fmt i with
508-
| '%' ->
509-
cont_s n "%" (succ i)
508+
| '%' | '@' as c ->
509+
cont_s n (String.make 1 c) (succ i)
510+
| '!' -> cont_f n (succ i)
511+
| ',' -> cont_s n "" (succ i)
510512
| 's' | 'S' as conv ->
511513
let (x : string) = get_arg spec n in
512514
let x = if conv = 's' then x else "\"" ^ String.escaped x ^ "\"" in
@@ -515,6 +517,8 @@ let scan_format fmt args n pos cont_s cont_a cont_t cont_f cont_m =
515517
if i = succ pos then x else
516518
format_string (extract_format fmt pos i widths) x in
517519
cont_s (next_index spec n) s (succ i)
520+
| '[' as conv ->
521+
bad_conversion_format fmt i conv
518522
| 'c' | 'C' as conv ->
519523
let (x : char) = get_arg spec n in
520524
let s =
@@ -546,6 +550,8 @@ let scan_format fmt args n pos cont_s cont_a cont_t cont_f cont_m =
546550
let n = Sformat.succ_index (get_index spec n) in
547551
let arg = get_arg Spec_none n in
548552
cont_a (next_index spec n) printer arg (succ i)
553+
| 'r' as conv ->
554+
bad_conversion_format fmt i conv
549555
| 't' ->
550556
let printer = get_arg spec n in
551557
cont_t (next_index spec n) printer (succ i)
@@ -570,8 +576,6 @@ let scan_format fmt args n pos cont_s cont_a cont_t cont_f cont_m =
570576
let s = format_int (extract_format_int 'n' fmt pos i widths) x in
571577
cont_s (next_index spec n) s (succ i)
572578
end
573-
| ',' -> cont_s n "" (succ i)
574-
| '!' -> cont_f n (succ i)
575579
| '{' | '(' as conv (* ')' '}' *) ->
576580
let (xf : ('a, 'b, 'c, 'd, 'e, 'f) format6) = get_arg spec n in
577581
let i = succ i in

‎stdlib/printf.mli

+22-16
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ val fprintf : out_channel -> ('a, out_channel, unit) format -> 'a
2020
[arg1] to [argN] according to the format string [format], and
2121
outputs the resulting string on the channel [outchan].
2222
23-
The format is a character string which contains two types of
23+
The format string is a character string which contains two types of
2424
objects: plain characters, which are simply copied to the output
2525
channel, and conversion specifications, each of which causes
2626
conversion and printing of arguments.
@@ -31,20 +31,23 @@ val fprintf : out_channel -> ('a, out_channel, unit) format -> 'a
3131
3232
In short, a conversion specification consists in the [%] character,
3333
followed by optional modifiers and a type which is made of one or
34-
two characters. The types and their meanings are:
34+
two characters.
3535
36-
- [d], [i], [n], [l], [L], or [N]: convert an integer argument to
37-
signed decimal.
38-
- [u]: convert an integer argument to unsigned decimal.
36+
The types and their meanings are:
37+
38+
- [d], [i]: convert an integer argument to signed decimal.
39+
- [u], [n], [l], [L], or [N]: convert an integer argument to
40+
unsigned decimal. Warning: [n], [l], [L], and [N] are
41+
used for [scanf], and should not be used for [printf].
3942
- [x]: convert an integer argument to unsigned hexadecimal,
4043
using lowercase letters.
4144
- [X]: convert an integer argument to unsigned hexadecimal,
4245
using uppercase letters.
4346
- [o]: convert an integer argument to unsigned octal.
4447
- [s]: insert a string argument.
45-
- [S]: insert a string argument in OCaml syntax (double quotes, escapes).
48+
- [S]: convert a string argument to OCaml syntax (double quotes, escapes).
4649
- [c]: insert a character argument.
47-
- [C]: insert a character argument in OCaml syntax (single quotes, escapes).
50+
- [C]: convert a character argument to OCaml syntax (single quotes, escapes).
4851
- [f]: convert a floating-point argument to decimal notation,
4952
in the style [dddd.ddd].
5053
- [F]: convert a floating-point argument to OCaml syntax ([dddd.]
@@ -54,37 +57,40 @@ val fprintf : out_channel -> ('a, out_channel, unit) format -> 'a
5457
- [g] or [G]: convert a floating-point argument to decimal notation,
5558
in style [f] or [e], [E] (whichever is more compact).
5659
- [B]: convert a boolean argument to the string [true] or [false]
57-
- [b]: convert a boolean argument (for backward compatibility; do not
58-
use in new programs).
60+
- [b]: convert a boolean argument (deprecated; do not use in new
61+
programs).
5962
- [ld], [li], [lu], [lx], [lX], [lo]: convert an [int32] argument to
6063
the format specified by the second letter (decimal, hexadecimal, etc).
6164
- [nd], [ni], [nu], [nx], [nX], [no]: convert a [nativeint] argument to
6265
the format specified by the second letter.
6366
- [Ld], [Li], [Lu], [Lx], [LX], [Lo]: convert an [int64] argument to
6467
the format specified by the second letter.
65-
- [a]: user-defined printer. Takes two arguments and applies the
68+
- [a]: user-defined printer. Take two arguments and apply the
6669
first one to [outchan] (the current output channel) and to the
6770
second argument. The first argument must therefore have type
6871
[out_channel -> 'b -> unit] and the second ['b].
6972
The output produced by the function is inserted in the output of
7073
[fprintf] at the current point.
71-
- [t]: same as [%a], but takes only one argument (with type
74+
- [t]: same as [%a], but take only one argument (with type
7275
[out_channel -> unit]) and apply it to [outchan].
7376
- [\{ fmt %\}]: convert a format string argument. The argument must
7477
have the same type as the internal format string [fmt].
75-
- [( fmt %)]: format string substitution. Takes a format string
76-
argument and substitutes it to the internal format string [fmt]
78+
- [( fmt %)]: format string substitution. Take a format string
79+
argument and substitute it to the internal format string [fmt]
7780
to print following arguments. The argument must have the same
7881
type as the internal format string [fmt].
7982
- [!]: take no argument and flush the output.
8083
- [%]: take no argument and output one [%] character.
81-
- [,]: the no-op delimiter for conversion specifications.
84+
- [\@]: take no argument and output one [\@] character.
85+
- [,]: take no argument and do nothing.
8286
8387
The optional [flags] are:
8488
- [-]: left-justify the output (default is right justification).
8589
- [0]: for numerical conversions, pad with zeroes instead of spaces.
86-
- [+]: for numerical conversions, prefix number with a [+] sign if positive.
87-
- space: for numerical conversions, prefix number with a space if positive.
90+
- [+]: for signed numerical conversions, prefix number with a [+]
91+
sign if positive.
92+
- space: for signed numerical conversions, prefix number with a
93+
space if positive.
8894
- [#]: request an alternate formatting style for numbers.
8995
9096
The optional [width] is an integer indicating the minimal

‎stdlib/scanf.ml

+66-34
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ let int_of_width_opt = function
438438
;;
439439

440440
let int_of_prec_opt = function
441-
| None -> 0
441+
| None -> max_int
442442
| Some prec -> prec
443443
;;
444444

@@ -999,31 +999,51 @@ type char_set =
999999
| Neg_set of string (* Negative (complementary) set. *)
10001000
;;
10011001

1002+
10021003
(* Char sets are read as sub-strings in the format string. *)
1003-
let read_char_set fmt i =
1004-
let lim = Sformat.length fmt - 1 in
1004+
let scan_range fmt j =
1005+
1006+
let len = Sformat.length fmt in
1007+
1008+
let buffer = Buffer.create len in
10051009

1006-
let rec find_in_set j =
1007-
if j > lim then incomplete_format fmt else
1010+
let rec scan_closing j =
1011+
if j >= len then incomplete_format fmt else
10081012
match Sformat.get fmt j with
1009-
| ']' -> j
1010-
| _ -> find_in_set (succ j)
1011-
1012-
and find_set i =
1013-
if i > lim then incomplete_format fmt else
1014-
match Sformat.get fmt i with
1015-
| ']' -> find_in_set (succ i)
1016-
| _ -> find_in_set i in
1017-
1018-
if i > lim then incomplete_format fmt else
1019-
match Sformat.get fmt i with
1020-
| '^' ->
1021-
let i = succ i in
1022-
let j = find_set i in
1023-
j, Neg_set (Sformat.sub fmt (Sformat.index_of_int i) (j - i))
1024-
| _ ->
1025-
let j = find_set i in
1026-
j, Pos_set (Sformat.sub fmt (Sformat.index_of_int i) (j - i))
1013+
| ']' -> j, Buffer.contents buffer
1014+
| '%' ->
1015+
let j = j + 1 in
1016+
if j >= len then incomplete_format fmt else
1017+
begin match Sformat.get fmt j with
1018+
| '%' | '@' as c ->
1019+
Buffer.add_char buffer c;
1020+
scan_closing (j + 1)
1021+
| c -> bad_conversion fmt j c
1022+
end
1023+
| c ->
1024+
Buffer.add_char buffer c;
1025+
scan_closing (j + 1) in
1026+
1027+
let scan_first_pos j =
1028+
if j >= len then incomplete_format fmt else
1029+
match Sformat.get fmt j with
1030+
| ']' as c ->
1031+
Buffer.add_char buffer c;
1032+
scan_closing (j + 1)
1033+
| _ -> scan_closing j in
1034+
1035+
let rec scan_first_neg j =
1036+
if j >= len then incomplete_format fmt else
1037+
match Sformat.get fmt j with
1038+
| '^' ->
1039+
let j = j + 1 in
1040+
let k, char_set = scan_first_pos j in
1041+
k, Neg_set char_set
1042+
| _ ->
1043+
let k, char_set = scan_first_pos j in
1044+
k, Pos_set char_set in
1045+
1046+
scan_first_neg j
10271047
;;
10281048

10291049
(* Char sets are now represented as bit vectors that are represented as
@@ -1370,18 +1390,19 @@ let scan_format ib ef fmt rv f =
13701390
let width = int_of_width_opt width_opt in
13711391
let prec = int_of_prec_opt prec_opt in
13721392
match Sformat.get fmt i with
1373-
| '%' as conv ->
1374-
check_char ib conv; scan_fmt ir f (succ i)
1393+
| '%' | '@' as c ->
1394+
check_char ib c;
1395+
scan_fmt ir f (succ i)
13751396
| 's' ->
1376-
let i, stp = scan_fmt_stoppers (succ i) in
1397+
let i, stp = scan_indication (succ i) in
13771398
let _x = scan_string stp width ib in
13781399
scan_fmt ir (stack f (token_string ib)) (succ i)
13791400
| 'S' ->
13801401
let _x = scan_String width ib in
13811402
scan_fmt ir (stack f (token_string ib)) (succ i)
13821403
| '[' (* ']' *) ->
1383-
let i, char_set = read_char_set fmt (succ i) in
1384-
let i, stp = scan_fmt_stoppers (succ i) in
1404+
let i, char_set = scan_range fmt (succ i) in
1405+
let i, stp = scan_indication (succ i) in
13851406
let _x = scan_chars_in_char_set stp char_set width ib in
13861407
scan_fmt ir (stack f (token_string ib)) (succ i)
13871408
| ('c' | 'C') when width = 0 ->
@@ -1458,12 +1479,23 @@ let scan_format ib ef fmt rv f =
14581479

14591480
| c -> bad_conversion fmt i c
14601481

1461-
and scan_fmt_stoppers i =
1462-
if i > lim then i - 1, [] else
1463-
match Sformat.get fmt i with
1464-
| '@' when i < lim -> let i = succ i in i, [Sformat.get fmt i]
1465-
| '@' when i = lim -> incomplete_format fmt
1466-
| _ -> i - 1, [] in
1482+
and scan_indication j =
1483+
if j > lim then j - 1, [] else
1484+
match Sformat.get fmt j with
1485+
| '@' ->
1486+
let k = j + 1 in
1487+
if k > lim then j - 1, [] else
1488+
begin match Sformat.get fmt k with
1489+
| '%' ->
1490+
let k = k + 1 in
1491+
if k > lim then j - 1, [] else
1492+
begin match Sformat.get fmt k with
1493+
| '%' | '@' as c -> k, [ c ]
1494+
| _c -> j - 1, []
1495+
end
1496+
| c -> k, [ c ]
1497+
end
1498+
| _c -> j - 1, [] in
14671499

14681500
scan_fmt in
14691501

0 commit comments

Comments
 (0)
Please sign in to comment.