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