def generate_input_for_struct(self, type_name, var_name, code, recursive_count): """Generate input for struct fields. """ self.struct_limit -= 1 if self.struct_limit < 0: return '' type_component = typeutil.parse_type(type_name) base = type_component['base'] _,fields = syntaxutil.parse_struct_code(code) result = '' for field_type_name,field_var_name in fields: if field_var_name not in self.needed_fields: continue field_type_component = typeutil.parse_type(field_type_name) if not type_component['pointer']: new_field_name = var_name + '.' + field_var_name else: new_field_name = '(' + type_component['pointer'][1:] + var_name + ')->' + field_var_name if self.is_same_struct(field_type_component['base'], type_component['base']): if recursive_count > 0: result += self.generate_input(field_type_name , new_field_name, recursive_count=recursive_count-1) else: result += new_field_name + '= NULL;\n' continue result += self.generate_input(field_type_name, new_field_name) return result
def generate_alloc_string(type_name, var_name): """Generate allocate string for the type_name. :pre-condition type_name.count('*') >0 If there are more than one '*', will create temp variables for allocate. struct A **var; struct A *tmp = (struct A *)malloc(sizeof(struct A)) tmp->a = malloc() tmp->b = malloc() var = &tmp; """ # green('generate alloc string for '+type_name + var_name) def get_uuid_tmp_name(name, idx): # if it is A->b, then we need to use b_tmp1 instead of A->b_tmp1 return name.replace('(','').replace(')','').replace('->','_').replace('.','_') + '_tmp'+str(idx) result = '' type_component = typeutil.parse_type(type_name) base = type_component['base'] pointer_level = type_component['pointer'].count('*') if pointer_level == 1: result += var_name + ' = ' +\ '(' + base + '*)malloc(sizeof(' + base + '));\n' else: # allocate for the tmp variable result += base + ' *'+get_uuid_tmp_name(var_name, 1) +\ ' = ('+base+'*)malloc(sizeof('+base+'));\n' # allocate for all level for i in range(pointer_level-2): var_name_tmp = get_uuid_tmp_name(var_name, i+2) last_name_tmp = get_uuid_tmp_name(var_name, i+1) result += type_name + ' ' + '*'*(i+2) + var_name_tmp+'=&'+last_name_tmp+';\n' result += var_name + '=&' + get_uuid_tmp_name(var_name, pointer_level-1)+';\n' return result
def generate_primitive_output(type_name, var_name): """do not generate output for void """ if 'void' in type_name: return '' type_component = typeutil.parse_type(type_name) base = type_component['base'] pointer = type_component['pointer'] result = 'printf("%' + typeutil.parse_primitive_type(base) + ' ", ' result += '*'*pointer.count('*') + var_name result += ');\n' return result
def generate_primitive_input(type_name, var_name): """generate init string for primitive type variables """ type_component = typeutil.parse_type(type_name) formatter = typeutil.parse_primitive_type(type_component['base']) result = 'scanf("%' + formatter + '", ' if not type_component['pointer']: result += '&' + var_name else: result += type_component['pointer'][1:] + var_name result += ');\n' return result
def generate_input(self, type_name, var_name, recursive_count=1): result = '' type_component = typeutil.parse_type(type_name) base = type_component['base'] pointer = type_component['pointer'] array = type_component['array'] if array: if config.get('handle_array') == 'true': return self.generate_input_for_array(type_name, var_name) else: return '' # alloc if pointer: # char array should be treated separately if config.get('handle_array') == 'true' and base == 'char': result += self.generate_input_for_array('char[]', var_name+'_array') result += var_name +' = '+var_name + '_array;\n' return result; result += generate_alloc_string(type_name, var_name) # init if typeutil.is_primitive_type(base): result += generate_primitive_input(type_name, var_name) elif local.check_struct_or_typedef(base.replace('struct','').strip()): if config.get('handle_struct') != 'true': return '' code = local.resolve_single_simple(base.replace('struct','').strip(), t='st') if '{' in code.strip() and code.strip().startswith('typedef struct'): code = code.replace('typedef','').strip() code = code[:code.rfind('}')+1] + ';' result += self.generate_input_for_struct(type_name, var_name, code, recursive_count) elif code.strip().startswith('struct'): result += self.generate_input_for_struct(type_name, var_name, code, recursive_count) elif code.startswith('typedef'): if code.startswith('typedef struct'): code = local.resolve_single_simple(base.replace('struct', '').strip(), t='s') if code: result += self.generate_input_for_struct(type_name, var_name, code, recursive_count) else: _,original = syntaxutil.parse_typedef_code(code) result += self.generate_input(original+pointer+array, var_name, recursive_count) else: logger.warning('Not recognized code for generate input') else: sys_type = systype.resolve(base) if sys_type: result += self.generate_input(sys_type+pointer+array, var_name) else: logger.warning('the type '+type_name+' is not solved for init') return result
def build(function_node): _,func_name, fields = syntaxutil.parse_function(function_node) code = '' function_code = domutil.get_text_content(function_node) instrumented_function = function_code[:function_code.find('{')+1]+'\nprintf("%d ", 1);\n'+function_code[function_code.find('{')+1:] code += includes code += instrumented_function code += '\nint main() {\n' for type_name, var_name in fields: code += type_name + ' ' + var_name + ';\n' # if typeutil.is_primitive_type(type_name) type_component = typeutil.parse_type(type_name) if typeutil.is_primitive_type(type_component['base']): code += instrumenter.generate_primitive_input(type_name, var_name) code += func_name + '(' + ','.join([var for _,var in fields]) + ');\n' code += '}\n' return code
def generate_input_for_array(self, type_name, var_name): result = '' type_component = typeutil.parse_type(type_name) base = type_component['base'] # now only support primitive type if not typeutil.is_primitive_type(base): return result # now only support char array if base != 'char': return result # Only support one dimension array if not self.helium_size_defined: result += 'int helium_size;\n' self.helium_size_defined = True result += 'scanf("%d", &helium_size);\n' result += base +' '+ var_name + '[helium_size];\n' # result += 'for (int i=0;i<helium_size;i++) {\n' # var_name = var_name + '[i]' # result += self.generate_input(base, var_name) # result += '}\n' result += 'scanf("%s", '+var_name+');\n' return result
def generate(self): os.makedirs(self.output_folder, exist_ok=True) with open(self.output_folder + "/generate.c", "w") as f: f.write('#include "support.h"\n') # main f.write("int main() {\n") f.write("//@HeliumInput\n") for var_name in self.inputs: type_name = self.inputs[var_name] type_component = typeutil.parse_type(type_name) base = type_component["base"] array = type_component["array"] pointer = type_component["pointer"] f.write(base + pointer + " " + var_name + array + ";\n") f.write("//@HeliumInputEnd\n") f.write("/**********Context********/\n") context_size = 0 function_size = 0 context_text = "" for node in self.context: context_text += domutil.get_text_content(node) context_text = re.sub(r"\breturn\b[^;\n]*;", "return 0;", context_text) if config.get("show_context") == "true": print(context_text) context_size = context_text.count("\n") + 1 f.write(context_text) f.write("\n}\n") # functions for function in self.functions.values(): text = domutil.get_text_content(function) function_size += text.count("\n") f.write(text) f.write("\n") if config.get("show_context_size") == "true": print("context size: " + str(context_size)) if function_size != 0: print("context function size: " + str(function_size)) f.close()
def generate_output_for_array(self, type_name, var_name): result = '' type_component = typeutil.parse_type(type_name) base = type_component['base'] result += 'printf("%ld ", sizeof('+var_name+')/sizeof('+base+'));\n' return result