|
| 1 | +/*******************************************************************\ |
| 2 | +
|
| 3 | +Module: Prepend/ splice a 0-ary function call in the beginning of a function |
| 4 | +e.g. for setting/ modelling the global environment |
| 5 | +
|
| 6 | +Author: Konstantinos Pouliasis |
| 7 | +
|
| 8 | +Date: July 2017 |
| 9 | +
|
| 10 | +\*******************************************************************/ |
| 11 | + |
| 12 | +/// \file |
| 13 | +/// Prepend a nullary call to another function |
| 14 | +// useful for context/ environment setting in arbitrary nodes |
| 15 | + |
| 16 | +#include "splice_call.h" |
| 17 | +#include <util/message.h> |
| 18 | +#include <util/string2int.h> |
| 19 | +#include <util/string_utils.h> |
| 20 | +#include <util/language.h> |
| 21 | +#include <goto-programs/goto_functions.h> |
| 22 | +#include <algorithm> |
| 23 | + |
| 24 | +// split the argument in caller/ callee two-position vector |
| 25 | +// expect input as a string of two names glued with comma: "caller,callee" |
| 26 | +static bool parse_caller_callee( |
| 27 | + const std::string &callercallee, |
| 28 | + std::vector<std::string> &result) |
| 29 | +{ |
| 30 | + split_string(callercallee, ',', result); |
| 31 | + return (result.size()!= 2); |
| 32 | +} |
| 33 | + |
| 34 | +bool splice_call( |
| 35 | + goto_functionst &goto_functions, |
| 36 | + const std::string &callercallee, |
| 37 | + const symbol_tablet &symbol_table, |
| 38 | + message_handlert &message_handler) |
| 39 | +{ |
| 40 | + messaget message(message_handler); |
| 41 | + const namespacet ns(symbol_table); |
| 42 | + std::vector<std::string> caller_callee; |
| 43 | + if(parse_caller_callee(callercallee, caller_callee)) |
| 44 | + { |
| 45 | + message.error() << "Expecting two function names seperated by a comma" |
| 46 | + << messaget::eom; |
| 47 | + return true; |
| 48 | + } |
| 49 | + goto_functionst::function_mapt::iterator caller_fun= |
| 50 | + goto_functions.function_map.find(caller_callee[0]); |
| 51 | + goto_functionst::function_mapt::const_iterator callee_fun= |
| 52 | + goto_functions.function_map.find(caller_callee[1]); |
| 53 | + if(caller_fun==goto_functions.function_map.end()) |
| 54 | + { |
| 55 | + message.error() << "Caller function does not exist" << messaget::eom; |
| 56 | + return true; |
| 57 | + } |
| 58 | + if(!caller_fun->second.body_available()) |
| 59 | + { |
| 60 | + message.error() << "Caller function has no available body" << messaget::eom; |
| 61 | + return true; |
| 62 | + } |
| 63 | + if(callee_fun==goto_functions.function_map.end()) |
| 64 | + { |
| 65 | + message.error() << "Callee function does not exist" << messaget::eom; |
| 66 | + return true; |
| 67 | + } |
| 68 | + goto_programt::const_targett start= |
| 69 | + caller_fun->second.body.instructions.begin(); |
| 70 | + goto_programt::targett g= |
| 71 | + caller_fun->second.body.insert_before(start); |
| 72 | + code_function_callt splice_call; |
| 73 | + splice_call.function()=ns.lookup(callee_fun->first).symbol_expr(); |
| 74 | + g->make_function_call(to_code_function_call(splice_call)); |
| 75 | + |
| 76 | + // update counters etc. |
| 77 | + goto_functions.update(); |
| 78 | + return false; |
| 79 | +} |
0 commit comments