Exemple #1
0
    def get_macros_expansions(self, files=None, macros_names=None):
        """Get dictionary with macros expansions (C only).

        DEPRECATED: use get_expansions() instead.

        Args:
            files: A list of files to narrow down returned dictionary
            macros_names: A list of macros names to find and return
        """

        exps = self.Macros.load_expansions(files)
        expansions = nested_dict()

        # Map new format of macros to the old one
        for exp_file, macro, _, _, _, args in traverse(exps, 6):
            if expansions[exp_file][macro]["args"]:
                expansions[exp_file][macro]["args"].extend(args)
            else:
                expansions[exp_file][macro]["args"] = args

        if macros_names:
            filtered_expansions = nested_dict()

            for file, macros in traverse(expansions, 2):
                if macros in macros_names:
                    filtered_expansions[file][macros] = expansions[file][
                        macros]

            return filtered_expansions

        return expansions
Exemple #2
0
    def get_macros_definitions(self, files=None, macros_names=None):
        """Get dictionary with macros definitions (C only).

        DEPRECATED: use get_macros() instead.

        Args:
            files: A list of files to narrow down returned dictionary
            macros_names: A list of macros names to find and return
        """

        macros = self.Macros.load_macros(files)

        definitions = nested_dict()

        # Map new format of macros to the old one
        for file, macro, line in traverse(macros, 3):
            if definitions[file][macro]:
                definitions[file][macro].append(line)
            else:
                definitions[file][macro] = [line]

        # Filter macro definitions by names
        if macros_names:
            filtered_definitions = nested_dict()

            for file, macros in traverse(definitions, 2):
                if macros in macros_names:
                    filtered_definitions[file][macros] = definitions[file][
                        macros]

            return filtered_definitions

        return definitions
Exemple #3
0
    def __process_functions_usages(self):
        for context_file, context_func, func, line in self.extensions[
                "Info"].iter_functions_usages():
            if self.is_builtin.match(func):
                continue

            if func not in self.funcs:
                self._error(
                    "Use of function without definition: {}".format(func))
                continue

            # For each function call there can be many definitions with the same name, defined in different files.
            # possible_files is a list of them.
            possible_files = tuple(f for f in self.funcs[func]
                                   if f != "unknown")

            if len(possible_files) == 0:
                self._error("No possible definitions for use: {}".format(func))
                continue

            # Assign priority number for each possible definition. Examples:
            # 3 means that definition is located in the same file as the call
            # 2 - in the same translation unit
            # 1 - in the object file that is linked with the object file that contains the call
            # 0 - definition is not found
            index = 3
            for files in ((f for f in possible_files if f == context_file),
                          (f for f in possible_files
                           if self._t_unit_is_common(f, context_file)),
                          (f for f in possible_files
                           if self._files_are_linked(f, context_file)),
                          ['unknown']):
                matched_files = tuple(files)
                if matched_files:
                    break
                index -= 1
            else:
                raise RuntimeError("We do not expect any other file class")

            if len(matched_files) > 1:
                self._error("Multiple matches for use: {} call in {}".format(
                    func, context_func))

            for possible_file in matched_files:
                if func not in self.used_in[possible_file]:
                    self.used_in[possible_file][func] = {
                        "used_in_file": nested_dict(),
                        "used_in_func": nested_dict()
                    }

                if context_func == "NULL":
                    self.used_in[possible_file][func]["used_in_file"][
                        context_file][line] = index
                else:
                    self.used_in[possible_file][func]["used_in_func"][
                        context_file][context_func][line] = index

                if possible_file == "unknown":
                    self._error("Can't match definition for use: {} {}".format(
                        func, context_file))
Exemple #4
0
    def __init__(self, work_dir, conf=None):
        super().__init__(work_dir, conf)

        self.macros = nested_dict()
        self.macros_folder = "macros"

        self.exps = nested_dict()
        self.exps_folder = "expansions"
Exemple #5
0
    def __init__(self, work_dir, conf=None):
        super().__init__(work_dir, conf)

        self.src_graph = dict()

        self.funcs = nested_dict()
        self.funcs_file = "functions.json"

        self.funcs_by_file = nested_dict()
        self.funcs_by_file_file = "functions_by_file.json"
        self.funcs_by_file_folder = "functions_by_file"
Exemple #6
0
    def __get_raw_locations(self):
        raw_locations = nested_dict()

        raw_locations = self.__get_raw_func_locations(raw_locations)
        raw_locations = self.__get_raw_macro_locations(raw_locations)

        return raw_locations
Exemple #7
0
    def __gen_ref_from_macro(self, locations):
        for def_file, macros in self.extensions["Macros"].yield_macros():
            if def_file == "unknown" or "def_macro" not in locations[def_file]:
                continue

            ref_from = nested_dict()

            for macro, loc_list in traverse(locations[def_file]["def_macro"],
                                            2):
                for loc_el in loc_list:
                    def_line = str(loc_el[0])

                    for exp_file in macros[def_file][macro][def_line]:
                        exp_lines = [
                            int(l) for l in macros[def_file][macro][def_line]
                            [exp_file]
                        ]
                        val = (loc_el, (exp_file, exp_lines))

                        if ref_from[def_file]["expand"]:
                            ref_from[def_file]["expand"].append(val)
                        else:
                            ref_from[def_file]["expand"] = [val]

            self.__dump_ref_from(ref_from)
Exemple #8
0
    def __gen_ref_from_func(self, locations):
        for file, callgraph in self.extensions["Callgraph"].yield_callgraph():
            ref_from = nested_dict()

            for func in self.funcs[file]:
                context_locs = self.__get_context_locs(file, func, callgraph)

                if file != "unknown" and func in locations[file]["def_func"]:
                    loc_list = locations[file]["def_func"][func]

                    for context_file, lines in context_locs:
                        for loc_el in loc_list:
                            val = (loc_el, (context_file, lines))

                            if ref_from[file]["call"]:
                                ref_from[file]["call"].append(val)
                            else:
                                ref_from[file]["call"] = [val]

                for decl_file in self.funcs[file][func]["declarations"]:
                    if func in locations[decl_file]["decl_func"]:
                        loc_list = locations[decl_file]["decl_func"][func]

                        for context_file, lines in context_locs:
                            for loc_el in loc_list:
                                val = (loc_el, (context_file, lines))

                                if ref_from[decl_file]["call"]:
                                    ref_from[decl_file]["call"].append(val)
                                else:
                                    ref_from[decl_file]["call"] = [val]

            self.__dump_ref_from(ref_from)
Exemple #9
0
    def __gen_ref_to_macro(self, locations):
        for exp_file, expansions in self.extensions["Macros"].yield_expansions(
        ):
            if exp_file == "unknown" or "expand" not in locations[exp_file]:
                continue

            ref_to = nested_dict()

            for macro, loc_list in traverse(locations[exp_file]["expand"], 2):
                for loc_el in loc_list:
                    exp_line = str(loc_el[0])

                    for def_file, def_line in traverse(
                            expansions[exp_file][macro][exp_line], 2):
                        if def_file == "unknown":
                            continue

                        val = (loc_el, (def_file, int(def_line)))

                        if ref_to[exp_file]["def_macro"]:
                            ref_to[exp_file]["def_macro"].append(val)
                        else:
                            ref_to[exp_file]["def_macro"] = [val]

            self.__dump_ref_to(ref_to)
Exemple #10
0
    def __parse_file(self,
                     file,
                     raw_locations,
                     ignore_errors=False,
                     encoding="utf8"):
        storage_file = self.extensions["Storage"].get_storage_path(file)

        if not os.path.exists(storage_file):
            # There may be some header files from CIF that are not in the storage
            if os.path.exists(file):
                self.extensions["Storage"].add_file(file)
            else:
                return None

        locations = nested_dict()

        sorted_locs = sorted(raw_locations[file], key=lambda x: int(x[0]))
        sorted_pos = 0

        try:
            if ignore_errors:
                fp = codecs.open(storage_file,
                                 "r",
                                 encoding=encoding,
                                 errors="ignore")
            else:
                fp = open(storage_file, "r", encoding=encoding)

            for i, s in enumerate(fp):
                if sorted_pos >= len(sorted_locs):
                    break

                while (sorted_pos < len(sorted_locs)
                       and int(sorted_locs[sorted_pos][0]) <= i + 1):
                    if i == int(sorted_locs[sorted_pos][0]) - 1:
                        line = int(sorted_locs[sorted_pos][0])
                        name = sorted_locs[sorted_pos][1]
                        ctype = sorted_locs[sorted_pos][2]

                        for lowest_index in self.__find_all(s, name):
                            val = (line, lowest_index,
                                   lowest_index + len(name))
                            if name in locations[ctype]:
                                locations[ctype][name].append(val)
                            else:
                                locations[ctype][name] = [val]

                            # Only one macro definition can be on a single line
                            if ctype == "def_macro":
                                break
                            # TODO: there may be a function call inside macro expansion

                    sorted_pos += 1

            return locations
        except UnicodeDecodeError:
            return self.__parse_file(file, raw_locations, ignore_errors=True)
        finally:
            fp.close()
Exemple #11
0
    def __init__(self, work_dir, conf=None):
        super().__init__(work_dir, conf)

        self.src_graph = dict()
        self.funcs = dict()

        self.err_log = os.path.join(self.work_dir, "err.log")

        self.callgraph = nested_dict()
        self.callgraph_folder = "callgraph"

        self.calls_by_ptr = nested_dict()
        self.calls_by_ptr_file = "calls_by_ptr.json"

        self.used_in = nested_dict()
        self.used_in_file = "used_in.json"

        self.is_builtin = re.compile(r'(__builtin)|(__compiletime)')
Exemple #12
0
    def __gen_ref_to_func(self, locations):
        for context_file, callgraph in self.extensions[
                "Callgraph"].yield_callgraph():
            calls = set()

            for context_func, _, file in traverse(callgraph[context_file], 3,
                                                  {2: "calls"}):
                if file not in self.funcs:
                    self._error("Can't find file: {!r}".format(file))
                    continue

                for func in callgraph[context_file][context_func]["calls"][
                        file]:
                    if func not in locations[context_file]["call"]:
                        # Probably because of macro expansion
                        continue

                    if func not in self.funcs[file]:
                        self._error("Can't find function: {!r} {!r}".format(
                            func, file))
                        continue

                    calls.add((file, func))

            ref_to = nested_dict()

            for file, func in calls:
                loc_list = locations[context_file]["call"][func]

                if self.funcs[file][func]["line"]:
                    def_line = int(self.funcs[file][func]["line"])

                    for loc_el in loc_list:
                        val = (loc_el, (file, def_line))

                        if ref_to[context_file]["def_func"]:
                            ref_to[context_file]["def_func"].append(val)
                        else:
                            ref_to[context_file]["def_func"] = [val]

                for decl_file in self.funcs[file][func]["declarations"]:
                    decl_line = int(self.funcs[file][func]["declarations"]
                                    [decl_file]["line"])

                    for loc_el in loc_list:
                        val = (loc_el, (decl_file, decl_line))

                        if ref_to[context_file]["decl_func"]:
                            ref_to[context_file]["decl_func"].append(val)
                        else:
                            ref_to[context_file]["decl_func"] = [val]

            self.__dump_ref_to(ref_to)
Exemple #13
0
 def __process_macros_definitions(self):
     for file, macro, line in self.extensions[
             "Info"].iter_macros_definitions():
         self.macros[file][macro][line] = nested_dict()