@@ -225,6 +225,87 @@ optionalt<exprt> string_insertion_builtin_functiont::eval(
225225 return make_string (result_value, type);
226226}
227227
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+
228309string_builtin_function_with_no_evalt::string_builtin_function_with_no_evalt (
229310 const exprt &return_code,
230311 const function_application_exprt &f,
0 commit comments