@@ -222,6 +222,84 @@ optionalt<exprt> string_insertion_builtin_functiont::eval(
222
222
return make_string (result_value, type);
223
223
}
224
224
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
+
225
303
string_builtin_function_with_no_evalt::string_builtin_function_with_no_evalt (
226
304
const exprt &return_code,
227
305
const function_application_exprt &f,
0 commit comments