Ejemplo n.º 1
0
    def __state_switch(self, states):
        key = ''.join(sorted([str(i) for i in states]))
        if key in self.__switchers_cache:
            return self.__switchers_cache[key]['call']

        # Generate switch function
        name = 'emg_switch_{}'.format(len(list(self.__switchers_cache.keys())))
        func = Function(name, 'int f(void)')
        # todo: Incorrect file
        func.definition_file = self._cmodel.entry_file

        # Generate switch body
        code = list()
        code.append('switch (ldv_undef_int()) {')
        for index in range(len(states)):
            code.append('\tcase {}: '.format(index) + '{')
            code.append('\t\treturn {};'.format(states[index]))
            code.append('\t\tbreak;')
            code.append('\t}')
        code.append('\tdefault: ldv_assume(0);')
        code.append('}')
        func.body.extend(code)

        # Add function
        self._cmodel.add_function_definition(func)

        invoke = '{}()'.format(name)
        self.__switchers_cache[key] = {
            'call': invoke,
            'function':  func
        }
        return invoke
Ejemplo n.º 2
0
    def _control_function(self, automaton):
        """
        Generate control function. This function generates a FunctionDefinition object without a body. It is required
        to call control function within code blocks until all code blocks are translated and control function body
        can be generated.

        :param automaton: Automaton object.
        :return: FunctionDefinition object.
        """
        if str(automaton) not in self._control_functions:
            # Check that this is an aspect function or not
            if automaton in self._model_fsa:
                name = 'emg_{}'.format(automaton.process.name)
                function_objs = self._source.get_source_functions(
                    automaton.process.name)
                if len(function_objs) == 0:
                    raise ValueError(
                        "Unfortunately there is no function {!r} found by the source analysis"
                        .format(automaton.process.name))
                else:
                    # We ignore there that fact that functions can have different scopes
                    function_obj = function_objs[0]
                params = []
                for position, param in enumerate(
                        function_obj.declaration.parameters):
                    if isinstance(param, str):
                        params.append(param)
                    else:
                        params.append(
                            param.to_string('arg{}'.format(str(position)),
                                            typedef='complex_and_params'))

                if len(params) == 0:
                    param_types = ['void']
                else:
                    param_types = params

                declaration = '{0} f({1})'.format(
                    function_obj.declaration.return_value.to_string(
                        '', typedef='complex_and_params'),
                    ', '.join(param_types))
                cf = Function(name, declaration)
            else:
                name = f'emg_{automaton.process.category}_{automaton.process.name}'
                if not get_or_die(self._conf,
                                  "direct control functions calls"):
                    declaration = 'void *f(void *data)'
                else:
                    declaration = 'void f(void *data)'
                cf = Function(name, declaration)
            cf.definition_file = automaton.process.file

            self._control_functions[automaton] = cf

        return self._control_functions[automaton]
Ejemplo n.º 3
0
    def __generate_alias(self, process, name, file, int_retval=False):
        new_name = "emg_{}".format(name)
        code = [
            "{}();".format("return {}".format(name) if int_retval else name)
        ]
        # Add definition
        func = Function(new_name,
                        "{}(void)".format("int {}".format(new_name) if int_retval else "void {}".format(new_name)))
        func.body = code
        process.add_definition(file, name, func.define())
        process.add_declaration('environment model', name,
                                'extern {} {}(void);\n'.format("int" if int_retval else "void", new_name))

        return new_name
Ejemplo n.º 4
0
    def _control_function(self, automaton):
        """
        Generate control function. This function generates a FunctionDefinition object without a body. It is required
        to call control function within code blocks until all code blocks are translated and control function body
        can be generated.

        :param automaton: Automaton object.
        :return: FunctionDefinition object.
        """
        if str(automaton) not in self._control_functions:
            # Check that this is an aspect function or not
            if automaton in self._model_fsa:
                return super(SimplestTranslator,
                             self)._control_function(automaton)
            else:
                name = f'emg_{automaton.process.category}_{automaton.process.name}'

                receives = [
                    r for r in automaton.process.actions.filter(
                        include={Receive}) if r.replicative
                ]
                if len(receives) == 0:
                    # This is the main process
                    declaration = f'void f(void)'
                elif len(receives) > 1:
                    raise RuntimeError(
                        f'Process {str(automaton.process)} has more than the one receive signal which'
                        f'is not supported by the translator. Choose an another one.'
                    )
                else:
                    action = receives.pop()
                    param_declarations = []

                    for index, param in enumerate(action.parameters):
                        receiver_access = automaton.process.resolve_access(
                            param)
                        var = automaton.determine_variable(
                            receiver_access.label)
                        param_declarations.append(
                            var.declaration.to_string(
                                '',
                                typedef='complex_and_params',
                                scope={automaton.process.file}))
                    args = ', '.join(param_declarations)
                    declaration = f'void f({args})'
                cf = Function(name, declaration)
                cf.definition_file = automaton.process.file
                self._control_functions[automaton] = cf
        return self._control_functions[automaton]
Ejemplo n.º 5
0
    def add_function(self, func, scope, fs, deps, cfiles):
        fs_desc = fs[scope][func]
        if scope == 'unknown':
            key = list(fs_desc['declarations'].keys())[0]
            signature = fs_desc['declarations'][key]['signature']
            func_intf = Function(func, signature)
            # Do not set definition file since it is out of scope of the target program fragment
        else:
            signature = fs_desc.get('signature')
            func_intf = Function(func, signature)
            func_intf.definition_file = scope

        # Set static
        if fs_desc.get('type') == "static":
            func_intf.static = True
        else:
            func_intf.static = False

        # Add declarations
        files = sortedcontainers.SortedSet()
        if func_intf.definition_file:
            files.add(func_intf.definition_file)
        if fs_desc['declarations']:
            files.update({
                f
                for f in fs_desc['declarations']
                if f != 'unknown' and f in deps
            })
        for file in files:
            if file not in cfiles and file not in func_intf.header_files:
                func_intf.header_files.append(file)
            for cfile in deps[file]:
                self.set_source_function(func_intf, cfile)
                func_intf.declaration_files.add(cfile)
Ejemplo n.º 6
0
def source_preset():
    cfiles = ['main.c', 'lib.c']

    source = Source(cfiles, [], dict())
    main_functions = {
        'f1': "static int f1(struct test *)",
        'f2': "static void f2(struct test *)",
        'f3': "static void f3(struct test *)",
        'f4': "static int f4(struct validation *)",
        'f5': "static void f4(void)"
    }
    external_functions = {
        "register_c1": "int register_c1(struct test *)",
        "deregister_c1": "void deregister_c1(struct test *)",
        "register_c2": "int register_c2(struct validation *)",
        "deregister_c2": "void deregister_c2(struct validation *)"
    }

    for name, declaration_str in main_functions.items():
        new = Function(name, declaration_str)
        new.definition_file = cfiles[0]
        source.set_source_function(new, cfiles[0])

    for name, declaration_str in external_functions.items():
        new = Function(name, declaration_str)
        new.definition_file = cfiles[1]
        source.set_source_function(new, cfiles[1])

    return source
Ejemplo n.º 7
0
    def __generate_calls(self, functions_collection):
        def indented_line(t, s):
            return (t * "\t") + s

        # Generate process
        ep = Process("main")
        ep._category = 'generic'
        ep.comment = "Call exported functions."
        ep.pretty_id = 'zephyr/generic'
        ep.process = ''

        caller_func = Function("ldv_zephr", "void a(void)")

        # Generate actions for all sequence
        expressions = []
        identifier = 0
        for func in functions_collection:
            for obj in functions_collection[func]:
                self.logger.info("Call function {!r} from {!r}".format(
                    func, obj.definition_file))
                expr = self.__generate_call(ep, func, obj, identifier)
                expressions.append(expr)

        # Generate process description
        tab = 0
        cnt = 0
        for expr in expressions:
            caller_func.body.append(indented_line(tab, "{}".format(expr)))
            cnt += 1

        ep.add_condition(
            'function_calls', [], ["{}();".format(caller_func.name)],
            'Call all initialization functions in asc order of level.')
        ep.process = "<function_calls>"
        ep.add_definition("environment model", caller_func.name,
                          caller_func.define() + ["\n"])

        return ep
Ejemplo n.º 8
0
def _model_factory(model_class):
    """The function allows to build a model with provided processes."""
    files = ['test.c']
    functions = {
        'f1': "static int f1(struct test *)",
        'f2': "static void f2(struct test *)"
    }
    source = Source(files, [], dict())
    for name, declaration_str in functions.items():
        new = Function(name, declaration_str)
        new.definition_file = files[0]
        source.set_source_function(new, files[0])
    spec = {
        "functions models": {
            "f1": model_class.f1_model,
            "f2": model_class.f2_model,
        },
        "environment processes": model_class.environment_models,
        "main process": model_class.entry
    }
    collection = CollectionDecoder(logging, dict()).parse_event_specification(source,
                                                                              json.loads(json.dumps(spec)),
                                                                              ProcessCollection())
    return collection
Ejemplo n.º 9
0
    def create_wrapper(self, wrapped_name: str, new_name: str, declaration: str) -> Function:
        """
        Create a wrapper of a static function and return an object of newly created function.

        :param wrapped_name: function name to wrap.
        :param new_name: a name of the wrapper.
        :param declaration: function declaration str.
        :return: Function object
        """
        new_func = Function(new_name, declaration)

        # Generate call
        ret = '' if not new_func.declaration.return_value or new_func.declaration.return_value == 'void' else 'return'

        # Generate params
        params = ', '.join(["arg{}".format(i) for i in range(len(new_func.declaration.parameters))])
        call = "{} {}({});".format(ret, wrapped_name, params)
        new_func.body.append(call)
        self._logger.info("Generated new wrapper function {!r}".format(new_func.name))
        return new_func
Ejemplo n.º 10
0
    def compose_entry_point(self, given_body):
        """
        Generate an entry point function for the environment model.

        :param given_body: Body of the main function provided by a translator.
        :return: List of C statements of the generated function body.
        """
        ep = Function(self.entry_name, "int {}(void)".format(self.entry_name))
        ep.definition_file = self.entry_file
        body = ['/* EMG_ACTION {' + '"thread": 1, "type": "CONTROL_FUNCTION_BEGIN", "comment": "Entry point \'{0}\'", '
                '"function": "{0}"'.format(self.entry_name) + '} */']

        # Init external allocated pointers
        cnt = 0
        functions = []
        if len(self.__external_allocated.keys()) > 0:
            for file, ext_vars in ((f, v) for f, v in self.__external_allocated.items() if v):
                func = Function('emg_allocate_external_{}'.format(cnt),
                                "void emg_allocate_external_{}(void)".format(cnt))
                func.declaration_files.add(file)
                func.definition_file = file

                init = ["{} = {}();".format(var.name, 'external_allocated_data') for var in ext_vars]
                func.body = init

                self.add_function_definition(func)
                self.add_function_declaration(self.entry_file, func, extern=True)
                functions.append(func)
                cnt += 1

            gl_init = Function('emg_initialize_external_data', 'void emg_initialize_external_data(void)')
            gl_init.declaration_files.add(self.entry_file)
            gl_init.definition_file = self.entry_file
            init_body = ['{}();'.format(func.name) for func in functions]
            gl_init.body = init_body
            self.add_function_definition(gl_init)
            body += [
                '/* Initialize external data */',
                'emg_initialize_external_data();'
            ]

        if self._conf.get("initialize requirements", True):
            body.append('ldv_initialize();')

        comment_data = {'action': 'scenarios'}
        body += [model_comment('ACTION_BEGIN', 'Begin Environment model scenarios', comment_data)] + given_body + \
                [model_comment('ACTION_END', other=comment_data)]

        if self._conf.get("check final state", True):
            body.append('ldv_check_final_state();')

        body += ['return 0;',
                 '/* EMG_ACTION {' +
                 '"comment": "Exit entry point \'{0}\'", "type": "CONTROL_FUNCTION_END", "function": "{0}"'.
                 format(self.entry_name) + '} */']

        ep.body = body
        self.add_function_definition(ep)

        return body
Ejemplo n.º 11
0
    def __generate_call(self, process, func_name, func_obj, identifier):
        """
        Generate a C code to call a particular function.

        :param process: Process object to add definitions and declarations.
        :param func_name: Function name.
        :param func_obj: Function object.
        :param identifier: Numerical identifier.
        :return: List of C statements
        """
        # Add declaration of caller
        caller_func = Function("emg_{}_caller_{}".format(func_name, identifier), "void a(void)")
        process.add_declaration("environment model", caller_func.name, caller_func.declare(True)[0])
        expression = ""
        body = []
        initializations = []

        # Check retval and cast to void call
        if func_obj.declaration.return_value and func_obj.declaration.return_value != 'void':
            expression += "(void) "

        # Get arguments and allocate memory for them
        args = []
        free_args = []
        for index, arg in enumerate(func_obj.declaration.parameters):
            if not isinstance(arg, str):
                argvar = Variable("emg_arg_{}".format(index), arg)
                body.append(argvar.declare(scope={func_obj.definition_file}) + ";")
                args.append(argvar.name)
                if isinstance(arg, Pointer):
                    elements = self.conf.get("initialize strings as null terminated")
                    if elements and str(arg) == 'char **':
                        if isinstance(elements, int) or elements.isnumeric():
                            elements = int(elements)
                        else:
                            elements = 'ldv_undef_int()'
                        argvar_len = Variable(argvar.name + '_len', 'int')

                        # Define explicitly number of arguments, since undef value is too difficult sometimes
                        initializations.append("int {} = {};".format(argvar_len.name, elements))
                        initializations.append("{} = (char **) ldv_xmalloc({} * sizeof(char *));".
                                               format(argvar.name, argvar_len.name))

                        # Initialize all elements but the last one
                        initializations.append("for (int i = 0; i < {} - 1; i++)".format(argvar_len.name))

                        # Some undefined data
                        initializations.append("\t{}[i] = (char *) external_allocated_data();".format(argvar.name))

                        # The last element is a string
                        initializations.append("{}[{}] = (char * ) 0;".format(argvar.name, elements - 1))
                        free_args.append(argvar.name)
                    elif self.conf.get("allocate external", True):
                        value = "external_allocated_data();"
                        initializations.append("{} = {}".format(argvar.name, value))
                    else:
                        if self.conf.get("allocate with sizeof", True):
                            apt = arg.points.to_string('', typedef='complex_and_params')
                            value = "ldv_xmalloc(sizeof({}));".\
                                format(apt if apt != 'void' else apt + '*')
                        else:
                            value = "ldv_xmalloc_unknown_size(0);"
                        free_args.append(argvar.name)
                        initializations.append("{} = {}".format(argvar.name, value))

        # Generate call
        expression += "{}({});".format(func_name, ", ".join(args))

        # Generate function body
        body += initializations + [expression]

        # Free memory
        for arg in free_args:
            body.append("ldv_free({});".format(arg))

        caller_func.body = body

        # Add definition of caller
        process.add_definition(func_obj.definition_file, caller_func.name, caller_func.define() + ["\n"])

        # Return call expression
        return "{}();".format(caller_func.name)
Ejemplo n.º 12
0
    def _dispatch(self, action, automaton):
        """
        Generate a code block for a dispatch action of the process for which the automaton is generated. A dispatch code
        block is always generated in a fixed form: as a function call of auxiliary function. Such a function contains
        switch or if operator to choose one of available optional receivers to send the signal. Implementation of
        particular dispatch to particular receiver is configurable and can be implemented differently in various
        translation.

        :param action: Action object.
        :param automaton: Automaton object which contains the dispatch.
        :return: [list of strings with lines of C code statements of the code block],
                 [list of strings with new local variable declarations required for the block],
                 [list of strings with boolean conditional expressions which guard code block entering],
                 [list of strings with model comments which embrace the code block]
        """
        code, v_code, conditions, comments = list(), list(), list(), list()

        # Determine peers to receive the signal
        automata_peers = sortedcontainers.SortedDict()
        if len(action.peers) > 0:
            # Do call only if model which can be called will not hang
            extract_relevant_automata(
                self._logger,
                self._event_fsa + self._model_fsa + [self._entry_fsa],
                automata_peers, action.peers, Receive)
        else:
            # Generate comment
            code.append(
                "/* Dispatch {!r} is not expected by any process, skipping the action */"
                .format(action.name))

        # Make comments
        if len(automata_peers) > 0:
            category = list(automata_peers.values()
                            )[0]['automaton'].process.category.upper()
            comment = action.comment.format(category)
        else:
            comment = 'Skip the action, since no peers has been found.'
        comments.append(action_model_comment(action, comment, begin=True))
        comments.append(action_model_comment(action, None, begin=False))

        # Add given conditions from a spec
        conditions = []
        if action.condition and len(action.condition) > 0:
            for statement in action.condition:
                cn = self._cmodel.text_processor(automaton, statement)
                conditions.extend(cn)

        if len(automata_peers) > 0:
            # Add conditions on base of dispatches
            checks = self._relevant_checks(automata_peers)
            if len(checks) > 0:
                if automaton in self._model_fsa:
                    conditions.append("({})".format(' || '.join(checks)))
                else:
                    # Convert conditions into assume, because according to signals semantics process could not proceed
                    # until it sends a signal and condition describes precondition to prevent signal sending to a
                    # wrong process.
                    if len(checks) > 0:
                        code.append('ldv_assume({});'.format(
                            ' || '.join(checks)))

            # Generate artificial function
            body = []

            if not self._conf.get('direct control functions calls'):
                body = ['int ret;']

            # Check dispatch type
            replicative = False
            for a_peer in automata_peers:
                for act in automata_peers[a_peer]['actions']:
                    if act.replicative:
                        replicative = True
                        break

            # Determine parameters
            df_parameters = []
            function_parameters = []

            # Add parameters
            for index in range(len(action.parameters)):
                # Determine dispatcher parameter
                # We expect strictly one
                dispatcher_access = automaton.process.resolve_access(
                    action.parameters[index])
                variable = automaton.determine_variable(
                    dispatcher_access.label)
                function_parameters.append(variable.declaration)
                df_parameters.append(variable.name)

            # Generate blocks on each receive to another process
            # You can implement your own translation with different implementations of the function
            pre, blocks, post = self._dispatch_blocks(action, automaton,
                                                      function_parameters,
                                                      automata_peers,
                                                      replicative)
            if len(blocks) > 0:
                body += pre

                # Print body of a dispatching function
                if action.broadcast:
                    for block in blocks:
                        body += block
                else:
                    imply_signals = self._conf.get('do not skip signals')
                    if len(blocks) > 2 or (len(blocks) == 2
                                           and not imply_signals):
                        body.append('switch (ldv_undef_int()) {')
                        for index in range(len(blocks)):
                            body.extend(
                                ['\tcase {}: '.format(index) + '{'] + \
                                ['\t\t' + stm for stm in blocks[index]] + \
                                ['\t\tbreak;',
                                 '\t};']
                            )
                        if imply_signals:
                            body.append('\tdefault: ldv_assume(0);')
                        body.append('};')
                    elif len(blocks) == 2 and imply_signals:
                        body.append('if (ldv_undef_int()) {')
                        body.extend(['\t' + stm for stm in blocks[0]])
                        body.extend(['}', 'else {'])
                        body.extend(['\t' + stm for stm in blocks[1]])
                        body.extend(['}'])
                    elif len(blocks) == 1 and not imply_signals:
                        body.append('if (ldv_undef_int()) {')
                        body.extend(['\t' + stm for stm in blocks[0]])
                        body.extend(['}'])
                    else:
                        body.extend(blocks[0])

                if len(function_parameters) > 0:
                    df = Function(
                        "emg_dispatch_{}_{}".format(str(action),
                                                    str(automaton)),
                        "void f({})".format(', '.join([
                            function_parameters[index].to_string(
                                'arg{}'.format(index),
                                typedef='complex_and_params')
                            for index in range(len(function_parameters))
                        ])))
                else:
                    df = Function(
                        "emg_dispatch_{}_{}".format(str(action),
                                                    str(automaton)),
                        "void f(void)")
                df.definition_file = automaton.process.file
                body.extend(post)
                body.append('return;')
                df.body.extend(body)

                # Add function definition
                self._cmodel.add_function_definition(df)

                code.extend(
                    ['{}({});'.format(df.name, ', '.join(df_parameters))])
            else:
                # This is becouse translation can have specific restrictions
                self._logger.debug(
                    f'No block to implement signal receive of actioon {str(action)} in {str(automaton)}'
                )
                code.append(
                    '/* Skip the dispatch because there is no process to receive the signal */'
                )
        else:
            self._logger.debug(
                f'No peers to implement signal receive of actioon {str(action)} in {str(automaton)}'
            )
            code.append(
                '/* Skip the dispatch because there is no process to receive the signal */'
            )

        return code, v_code, conditions, comments
Ejemplo n.º 13
0
    def __generate_insmod_process(self, source, inits, exits,
                                  kernel_initializations):
        self.logger.info(
            "Generate artificial process description to call Init and Exit module functions 'insmod'"
        )
        ep = Process("insmod")
        ep.comment = "Initialize or exit module."
        ep.self_parallelism = False

        # Add subprocesses finally
        process = ''
        for i, pair in enumerate(inits):
            process += "<{0}>.(<init_failed_{1}>".format(pair[1], i)
            for j, pair2 in enumerate(exits[::-1]):
                if pair2[0] == pair[0]:
                    break
            j = 1
            for _, exit_name in exits[:j - 1:-1]:
                process += ".<{}>".format(exit_name)
            process += "|<init_success_{}>.".format(i)

        for _, exit_name in exits:
            process += "<{}>.".format(exit_name)
        # Remove the last dot
        process = process[:-1]

        process += ")" * len(inits)
        if kernel_initializations and inits:
            process += "<kernel_initialization>." \
                       "(<kerninit_success> | <kerninit_failed>.(" + process + "))"
        elif kernel_initializations and not inits:
            process += "<kernel_initialization>.(<kernel_initialization_success> | <kernel_initialization_fail>)"
        elif not inits and not kernel_initializations:
            raise NotImplementedError(
                "There is no both kernel initialization functions and module initialization "
                "functions")

        # This populates all actions
        parse_process(ep, process)
        ep.actions.populate_with_empty_descriptions()

        if len(kernel_initializations) > 0:
            body = ["int ret;"]
            label_name = 'emg_kernel_initialization_exit'

            # Generate kernel initializations
            for name, calls in kernel_initializations:
                for filename, func_name in calls:
                    func = source.get_source_function(func_name, filename)
                    if func:
                        retval = not func.declaration.return_value == 'void'
                    else:
                        raise RuntimeError(
                            "Cannot resolve function {!r} in file {!r}".format(
                                name, filename))
                    new_name = self.__generate_alias(ep, func_name, filename,
                                                     retval)
                    statements = []
                    if retval:
                        statements.extend([
                            "ret = {}();".format(new_name),
                            "ret = ldv_post_init(ret);", "if (ret)",
                            "\tgoto {};".format(label_name)
                        ])
                    else:
                        statements.append("{}();".format(new_name))

                    body.extend(statements)
            body.extend(["{}:".format(label_name), "return ret;"])
            func = Function('emg_kernel_init', 'int emg_kernel_init(void)')
            func.body = body
            addon = func.define()
            ep.add_definition('environment model', 'emg_kernel_init', addon)

            ki_subprocess = ep.actions['kernel initialization']
            ki_subprocess.statements = ["%ret% = emg_kernel_init();"]
            ki_subprocess.comment = 'Kernel initialization stage.'
            ki_subprocess.trace_relevant = True

            ki_success = ep.actions['ki_success']
            ki_success.condition = ["%ret% == 0"]
            ki_success.comment = "Kernel initialization is successful."

            ki_failed = ep.actions['kerninit_failed']
            ki_failed.condition = ["%ret% != 0"]
            ki_failed.comment = "Kernel initialization is unsuccessful."
        if len(inits) > 0:
            # Generate init subprocess
            for filename, init_name in inits:
                self.logger.debug("Found init function {!r}".format(init_name))
                new_name = self.__generate_alias(ep, init_name, filename, True)
                init_subprocess = ep.actions[init_name]
                init_subprocess.comment = 'Initialize the module after insmod with {!r} function.'.format(
                    init_name)
                init_subprocess.statements = [
                    "%ret% = {}();".format(new_name),
                    "%ret% = ldv_post_init(%ret%);"
                ]
                init_subprocess.trace_relevant = True

        # Add ret label
        ep.add_label('ret', import_declaration("int label"))

        # Generate exit subprocess
        if len(exits) == 0:
            self.logger.debug("There is no exit function found")
        else:
            for filename, exit_name in exits:
                self.logger.debug("Found exit function {!r}".format(exit_name))
                new_name = self.__generate_alias(ep, exit_name, filename,
                                                 False)
                exit_subprocess = ep.actions[exit_name]
                exit_subprocess.comment = 'Exit the module before its unloading with {!r} function.'.format(
                    exit_name)
                exit_subprocess.statements = ["{}();".format(new_name)]
                exit_subprocess.trace_relevant = True

        # Generate successful conditions
        for action in (a for a in ep.actions.filter(include={Block})
                       if str(a).startswith('init_success')):
            action.condition = ["%ret% == 0"]
            action.comment = "Module has been initialized."

        # Generate else branch
        for action in (a for a in ep.actions.filter(include={Block})
                       if str(a).startswith('init_failed')):
            action.condition = ["%ret% != 0"]
            action.comment = "Failed to initialize the module."

        return ep