@@ -225,6 +225,87 @@ optionalt<exprt> string_insertion_builtin_functiont::eval(
225
225
return make_string (result_value, type);
226
226
}
227
227
228
+ // / Constructor from arguments of a function application.
229
+ // / The arguments in `fun_args` should be in order:
230
+ // / an integer `result.length`, a character pointer `&result[0]`,
231
+ // / an integer `i` which is to be converted to a string.
232
+ string_creation_builtin_functiont::string_creation_builtin_functiont (
233
+ const exprt &return_code,
234
+ const std::vector<exprt> &fun_args,
235
+ array_poolt &array_pool)
236
+ : string_builtin_functiont(return_code)
237
+ {
238
+ PRECONDITION (fun_args.size () >= 3 );
239
+ result = array_pool.find (fun_args[1 ], fun_args[0 ]);
240
+ arg = fun_args[2 ];
241
+ }
242
+
243
+ optionalt<exprt> string_of_int_builtin_functiont::eval (
244
+ const std::function<exprt(const exprt &)> &get_value) const
245
+ {
246
+ const auto arg_value = numeric_cast<mp_integer>(get_value (arg));
247
+ if (!arg_value)
248
+ return {};
249
+ static std::string digits = " 0123456789abcdefghijklmnopqrstuvwxyz" ;
250
+ const auto radix_value = numeric_cast<mp_integer>(get_value (radix));
251
+ if (!radix_value || *radix_value > digits.length ())
252
+ return {};
253
+
254
+ mp_integer current_value = *arg_value;
255
+ std::vector<mp_integer> right_to_left_characters;
256
+ if (current_value < 0 )
257
+ current_value = -current_value;
258
+ if (current_value == 0 )
259
+ right_to_left_characters.emplace_back (' 0' );
260
+ while (current_value > 0 )
261
+ {
262
+ const auto digit_value = (current_value % *radix_value).to_ulong ();
263
+ right_to_left_characters.emplace_back (digits.at (digit_value));
264
+ current_value /= *radix_value;
265
+ }
266
+ if (*arg_value < 0 )
267
+ right_to_left_characters.emplace_back (' -' );
268
+
269
+ const auto length = right_to_left_characters.size ();
270
+ const auto length_expr = from_integer (length, result.length ().type ());
271
+ const array_typet type (result.type ().subtype (), length_expr);
272
+ return make_string (
273
+ right_to_left_characters.rbegin (),
274
+ right_to_left_characters.rend (),
275
+ type);
276
+ }
277
+
278
+ exprt string_of_int_builtin_functiont::length_constraint () const
279
+ {
280
+ const typet &type = result.length ().type ();
281
+ const auto radix_opt = numeric_cast<std::size_t >(radix);
282
+ const auto radix_value = radix_opt.has_value () ? radix_opt.value () : 2 ;
283
+ const std::size_t upper_bound =
284
+ max_printed_string_length (arg.type (), radix_value);
285
+ const exprt negative_arg =
286
+ binary_relation_exprt (arg, ID_le, from_integer (0 , type));
287
+ const exprt absolute_arg =
288
+ if_exprt (negative_arg, unary_minus_exprt (arg), arg);
289
+
290
+ exprt size_expr = from_integer (1 , type);
291
+ std::size_t current_size = 2 ;
292
+ for (
293
+ exprt min_int_with_current_size = radix;
294
+ current_size <= upper_bound + 1 ;
295
+ ++current_size,
296
+ min_int_with_current_size = mult_exprt (radix, min_int_with_current_size))
297
+ {
298
+ const exprt at_least_current_size =
299
+ binary_relation_exprt (absolute_arg, ID_ge, min_int_with_current_size);
300
+ size_expr = if_exprt (
301
+ at_least_current_size, from_integer (current_size, type), size_expr);
302
+ }
303
+
304
+ const exprt size_expr_with_sign = if_exprt (
305
+ negative_arg, plus_exprt (size_expr, from_integer (1 , type)), size_expr);
306
+ return equal_exprt (result.length (), size_expr_with_sign);
307
+ }
308
+
228
309
string_builtin_function_with_no_evalt::string_builtin_function_with_no_evalt (
229
310
const exprt &return_code,
230
311
const function_application_exprt &f,
0 commit comments