blob: 8d7c0f1159db67241548f7f4db65505ecfde8af9 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
|
(***********************************************************************)
(* *)
(* Caml Special Light *)
(* *)
(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
(* *)
(* Copyright 1995 Institut National de Recherche en Informatique et *)
(* Automatique. Distributed only by permission. *)
(* *)
(***********************************************************************)
(* $Id$ *)
external format_int: string -> int -> string = "format_int"
external format_float: string -> float -> string = "format_float"
let fprintf outchan format =
let format = (Obj.magic format : string) in
let rec doprn i =
if i >= String.length format then
Obj.magic ()
else begin
let c = String.unsafe_get format i in
if c <> '%' then begin
output_char outchan c;
doprn (succ i)
end else begin
let j = skip_args (succ i) in
match String.unsafe_get format j with
'%' ->
output_char outchan '%';
doprn (succ j)
| 's' ->
Obj.magic(fun s ->
if j <= i+1 then
output_string outchan s
else begin
let p =
try
int_of_string (String.sub format (i+1) (j-i-1))
with _ ->
invalid_arg "fprintf: bad %s format" in
if p > 0 & String.length s < p then begin
output_string outchan
(String.make (p - String.length s) ' ');
output_string outchan s
end else if p < 0 & String.length s < -p then begin
output_string outchan s;
output_string outchan
(String.make (-p - String.length s) ' ')
end else
output_string outchan s
end;
doprn (succ j))
| 'c' ->
Obj.magic(fun c ->
output_char outchan c;
doprn (succ j))
| 'd' | 'o' | 'x' | 'X' | 'u' ->
Obj.magic(fun n ->
output_string outchan
(format_int (String.sub format i (j-i+1)) n);
doprn (succ j))
| 'f' | 'e' | 'E' | 'g' | 'G' ->
Obj.magic(fun f ->
output_string outchan
(format_float (String.sub format i (j-i+1)) f);
doprn (succ j))
| 'b' ->
Obj.magic(fun b ->
output_string outchan (string_of_bool b);
doprn (succ j))
| 'a' ->
Obj.magic(fun printer arg ->
printer outchan arg;
doprn(succ j))
| 't' ->
Obj.magic(fun printer ->
printer outchan;
doprn(succ j))
| c ->
invalid_arg ("fprintf: unknown format")
end
end
and skip_args j =
match String.unsafe_get format j with
'0' .. '9' | ' ' | '.' | '-' -> skip_args (succ j)
| c -> j
in doprn 0
let printf fmt = fprintf stdout fmt
and eprintf fmt = fprintf stderr fmt
let sprintf format =
let format = (Obj.magic format : string) in
let rec doprn start i accu =
if i >= String.length format then begin
let res =
if i > start
then String.sub format start (i-start) :: accu
else accu in
Obj.magic(String.concat "" (List.rev res))
end else
if String.unsafe_get format i <> '%' then
doprn start (i+1) accu
else begin
let accu1 =
if i > start then
String.sub format start (i-start) :: accu
else accu in
let j = skip_args (succ i) in
match String.unsafe_get format j with
'%' ->
doprn j (succ j) accu1
| 's' ->
Obj.magic(fun s ->
let accu2 =
if j <= i+1 then
s :: accu1
else begin
let p =
try
int_of_string (String.sub format (i+1) (j-i-1))
with _ ->
invalid_arg "fprintf: bad %s format" in
if p > 0 & String.length s < p then
s :: String.make (p - String.length s) ' ' :: accu1
else if p < 0 & String.length s < -p then
String.make (-p - String.length s) ' ' :: s :: accu1
else
s :: accu1
end in
doprn (succ j) (succ j) accu2)
| 'c' ->
Obj.magic(fun c ->
doprn (succ j) (succ j) (String.make 1 c :: accu1))
| 'd' | 'o' | 'x' | 'X' | 'u' ->
Obj.magic(fun n ->
doprn (succ j) (succ j)
(format_int (String.sub format i (j-i+1)) n :: accu1))
| 'f' | 'e' | 'E' | 'g' | 'G' ->
Obj.magic(fun f ->
doprn (succ j) (succ j)
(format_float (String.sub format i (j-i+1)) f :: accu1))
| 'b' ->
Obj.magic(fun b ->
doprn (succ j) (succ j) (string_of_bool b :: accu1))
| 'a' ->
Obj.magic(fun printer arg ->
doprn (succ j) (succ j) (printer () arg :: accu1))
| 't' ->
Obj.magic(fun printer ->
doprn (succ j) (succ j) (printer () :: accu1))
| c ->
invalid_arg ("sprintf: unknown format")
end
and skip_args j =
match String.unsafe_get format j with
'0' .. '9' | ' ' | '.' | '-' -> skip_args (succ j)
| c -> j
in doprn 0 0 []
|