11
11
12
12
#include " printf_formatter.h"
13
13
14
- #include < sstream>
15
-
16
14
#include < util/c_types.h>
15
+ #include < util/expr_util.h>
17
16
#include < util/format_constant.h>
18
17
#include < util/pointer_expr.h>
19
18
#include < util/simplify_expr.h>
20
19
#include < util/std_expr.h>
21
20
21
+ #include < sstream>
22
+
22
23
const exprt printf_formattert::make_type (
23
24
const exprt &src, const typet &dest)
24
25
{
@@ -66,6 +67,8 @@ void printf_formattert::process_format(std::ostream &out)
66
67
format_constant.min_width =0 ;
67
68
format_constant.zero_padding =false ;
68
69
70
+ std::string length_modifier;
71
+
69
72
char ch=next ();
70
73
71
74
if (ch==' 0' ) // leading zeros
@@ -94,6 +97,56 @@ void printf_formattert::process_format(std::ostream &out)
94
97
}
95
98
}
96
99
100
+ switch (ch)
101
+ {
102
+ case ' h' :
103
+ ch = next ();
104
+ if (ch == ' h' )
105
+ {
106
+ length_modifier = " hh" ;
107
+ ch = next ();
108
+ }
109
+ else
110
+ {
111
+ length_modifier = " h" ;
112
+ }
113
+ break ;
114
+
115
+ case ' l' :
116
+ ch = next ();
117
+ if (ch == ' l' )
118
+ {
119
+ length_modifier = " ll" ;
120
+ ch = next ();
121
+ }
122
+ else
123
+ {
124
+ length_modifier = " l" ;
125
+ }
126
+ break ;
127
+
128
+ case ' q' :
129
+ ch = next ();
130
+ length_modifier = " ll" ;
131
+ break ;
132
+
133
+ case ' L' :
134
+ case ' j' :
135
+ case ' z' :
136
+ case ' t' :
137
+ length_modifier = ch;
138
+ ch = next ();
139
+ break ;
140
+
141
+ case ' Z' :
142
+ ch = next ();
143
+ length_modifier = " z" ;
144
+ break ;
145
+
146
+ default :
147
+ break ;
148
+ }
149
+
97
150
switch (ch)
98
151
{
99
152
case ' %' :
@@ -105,17 +158,23 @@ void printf_formattert::process_format(std::ostream &out)
105
158
format_constant.style =format_spect::stylet::SCIENTIFIC;
106
159
if (next_operand==operands.end ())
107
160
break ;
108
- out << format_constant (
109
- make_type (*(next_operand++), double_type ()));
161
+ if (length_modifier == " L" )
162
+ out << format_constant (make_type (*(next_operand++), long_double_type ()));
163
+ else
164
+ out << format_constant (make_type (*(next_operand++), double_type ()));
110
165
break ;
111
166
167
+ case ' a' : // TODO: hexadecimal output
168
+ case ' A' : // TODO: hexadecimal output
112
169
case ' f' :
113
170
case ' F' :
114
171
format_constant.style =format_spect::stylet::DECIMAL;
115
172
if (next_operand==operands.end ())
116
173
break ;
117
- out << format_constant (
118
- make_type (*(next_operand++), double_type ()));
174
+ if (length_modifier == " L" )
175
+ out << format_constant (make_type (*(next_operand++), long_double_type ()));
176
+ else
177
+ out << format_constant (make_type (*(next_operand++), double_type ()));
119
178
break ;
120
179
121
180
case ' g' :
@@ -125,58 +184,130 @@ void printf_formattert::process_format(std::ostream &out)
125
184
format_constant.precision =1 ;
126
185
if (next_operand==operands.end ())
127
186
break ;
128
- out << format_constant (
129
- make_type (*(next_operand++), double_type ()));
187
+ if (length_modifier == " L" )
188
+ out << format_constant (make_type (*(next_operand++), long_double_type ()));
189
+ else
190
+ out << format_constant (make_type (*(next_operand++), double_type ()));
130
191
break ;
131
192
193
+ case ' S' :
194
+ length_modifier = ' l' ;
132
195
case ' s' :
133
196
{
134
197
if (next_operand==operands.end ())
135
198
break ;
136
199
// this is the address of a string
137
200
const exprt &op=*(next_operand++);
138
201
if (
139
- op.id () == ID_address_of &&
140
- to_address_of_expr (op).object ().id () == ID_index &&
141
- to_index_expr (to_address_of_expr (op).object ()).array ().id () ==
142
- ID_string_constant)
202
+ auto pointer_constant =
203
+ expr_try_dynamic_cast<annotated_pointer_constant_exprt>(op))
143
204
{
144
- out << format_constant (
145
- to_index_expr (to_address_of_expr (op).object ()).array ());
205
+ if (
206
+ auto address_of = expr_try_dynamic_cast<address_of_exprt>(
207
+ skip_typecast (pointer_constant->symbolic_pointer ())))
208
+ {
209
+ if (address_of->object ().id () == ID_string_constant)
210
+ {
211
+ out << format_constant (address_of->object ());
212
+ }
213
+ else if (
214
+ auto index_expr =
215
+ expr_try_dynamic_cast<index_exprt>(address_of->object ()))
216
+ {
217
+ if (
218
+ index_expr->index ().is_zero () &&
219
+ index_expr->array ().id () == ID_string_constant)
220
+ {
221
+ out << format_constant (index_expr->array ());
222
+ }
223
+ }
224
+ }
146
225
}
147
226
}
148
227
break ;
149
228
150
229
case ' d' :
230
+ case ' i' :
231
+ {
151
232
if (next_operand==operands.end ())
152
233
break ;
153
- out << format_constant (
154
- make_type (*(next_operand++), signed_int_type ()));
234
+ typet conversion_type;
235
+ if (length_modifier == " hh" )
236
+ conversion_type = signed_char_type ();
237
+ else if (length_modifier == " h" )
238
+ conversion_type = signed_short_int_type ();
239
+ else if (length_modifier == " l" )
240
+ conversion_type = signed_long_int_type ();
241
+ else if (length_modifier == " ll" )
242
+ conversion_type = signed_long_long_int_type ();
243
+ else if (length_modifier == " j" ) // intmax_t
244
+ conversion_type = signed_long_long_int_type ();
245
+ else if (length_modifier == " z" )
246
+ conversion_type = signed_size_type ();
247
+ else if (length_modifier == " t" )
248
+ conversion_type = pointer_diff_type ();
249
+ else
250
+ conversion_type = signed_int_type ();
251
+ out << format_constant (make_type (*(next_operand++), conversion_type));
252
+ }
155
253
break ;
156
254
157
- case ' D' :
158
- if (next_operand==operands.end ())
159
- break ;
160
- out << format_constant (
161
- make_type (*(next_operand++), signed_long_int_type ()));
255
+ case ' o' : // TODO: octal output
256
+ case ' x' : // TODO: hexadecimal output
257
+ case ' X' : // TODO: hexadecimal output
258
+ case ' u' :
259
+ {
260
+ if (next_operand == operands.end ())
261
+ break ;
262
+ typet conversion_type;
263
+ if (length_modifier == " hh" )
264
+ conversion_type = unsigned_char_type ();
265
+ else if (length_modifier == " h" )
266
+ conversion_type = unsigned_short_int_type ();
267
+ else if (length_modifier == " l" )
268
+ conversion_type = unsigned_long_int_type ();
269
+ else if (length_modifier == " ll" )
270
+ conversion_type = unsigned_long_long_int_type ();
271
+ else if (length_modifier == " j" ) // intmax_t
272
+ conversion_type = unsigned_long_long_int_type ();
273
+ else if (length_modifier == " z" )
274
+ conversion_type = size_type ();
275
+ else if (length_modifier == " t" )
276
+ conversion_type = pointer_diff_type ();
277
+ else
278
+ conversion_type = unsigned_int_type ();
279
+ out << format_constant (make_type (*(next_operand++), conversion_type));
280
+ }
162
281
break ;
163
282
164
- case ' u' :
165
- if (next_operand==operands.end ())
283
+ case ' C' :
284
+ length_modifier = ' l' ;
285
+ case ' c' :
286
+ if (next_operand == operands.end ())
287
+ break ;
288
+ if (length_modifier == " l" )
289
+ out << format_constant (make_type (*(next_operand++), wchar_t_type ()));
290
+ else
291
+ out << format_constant (
292
+ make_type (*(next_operand++), unsigned_char_type ()));
166
293
break ;
167
- out << format_constant (
168
- make_type (*(next_operand++), unsigned_int_type ()));
169
- break ;
170
294
171
- case ' U' :
172
- if (next_operand==operands.end ())
295
+ case ' p' :
296
+ // TODO: hexadecimal output
297
+ out << format_constant (make_type (*(next_operand++), size_type ()));
173
298
break ;
174
- out << format_constant (
175
- make_type (*(next_operand++), unsigned_long_int_type ()));
176
- break ;
177
299
178
- default :
179
- out << ' %' << ch;
300
+ case ' n' :
301
+ if (next_operand == operands.end ())
302
+ break ;
303
+ // printf would store the number of characters written so far in the
304
+ // object pointed to by this operand. We do not implement this side-effect
305
+ // here, and just skip one operand.
306
+ ++next_operand;
307
+ break ;
308
+
309
+ default :
310
+ out << ' %' << ch;
180
311
}
181
312
}
182
313
0 commit comments