|  | 
|  | 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