This file is indexed.

/usr/lib/python3/dist-packages/pygccxml/declarations/pattern_parser.py is in python3-pygccxml 1.8.0-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# Copyright 2014-2016 Insight Software Consortium.
# Copyright 2004-2008 Roman Yakovenko.
# Distributed under the Boost Software License, Version 1.0.
# See http://www.boost.org/LICENSE_1_0.txt

"""
Implementation details

"""

import re


class parser_t(object):

    """implementation details"""

    def __init__(
            self,
            pattern_char_begin,
            pattern_char_end,
            pattern_char_separator):
        self.__begin = pattern_char_begin
        self.__end = pattern_char_end
        self.__separator = pattern_char_separator
        # right now parser does not take into account next qualifiers, but it
        # will
        self.__text_qualifier = '"'
        self.__char_qualifier = "'"
        self.__escape = '\\'

    def has_pattern(self, decl_string):
        """
        Implementation detail

        """
        if self.__begin == "<":
            # Cleanup parentheses blocks before checking for the pattern
            # See also the args() method (in this file) for more explanations.
            decl_string = re.sub("\s\(.*?\)", "", decl_string).strip()

        last_part = decl_string.split('::')[-1]
        return (
            -1 != decl_string.find(self.__begin) and -
            1 != last_part.find(self.__end)
        )

    def name(self, decl_string):
        """implementation details"""
        if not self.has_pattern(decl_string):
            return decl_string
        args_begin = decl_string.find(self.__begin)
        return decl_string[0: args_begin].strip()

    def __find_args_separator(self, decl_string, start_pos):
        """implementation details"""
        bracket_depth = 0
        for index, ch in enumerate(decl_string[start_pos:]):
            if ch not in (self.__begin, self.__end, self.__separator):
                continue  # I am interested only in < and >
            elif self.__separator == ch:
                if not bracket_depth:
                    return index + start_pos
            elif self.__begin == ch:
                bracket_depth += 1
            elif not bracket_depth:
                return index + start_pos
            else:
                bracket_depth -= 1
        return -1

    def args(self, decl_string):
        """
        Extracts a list of arguments from the provided declaration string.

        Implementation detail. Example usages:
        Input: myClass<std::vector<int>, std::vector<double>>
        Output: [std::vector<int>, std::vector<double>]

        Args:
           decl_string (str): the full declaration string

        Returns:
            list: list of arguments as strings

        """
        args_begin = decl_string.find(self.__begin)
        args_end = decl_string.rfind(self.__end)
        if -1 in (args_begin, args_end) or args_begin == args_end:
            raise RuntimeError(
                "%s doesn't validate template instantiation string" %
                decl_string)

        args_only = decl_string[args_begin + 1: args_end].strip()

        # The list of arguments to be returned
        args = []

        parentheses_blocks = []
        prev_span = 0
        if self.__begin == "<":
            # In case where we are splitting template names, there
            # can be parentheses blocks (for arguments) that need to be taken
            # care of.

            # Build a regex matching a space (\s)
            # + something inside parentheses
            regex = re.compile("\s\(.*?\)")
            for m in regex.finditer(args_only):
                # Store the position and the content
                parentheses_blocks.append([m.start() - prev_span, m.group()])
                prev_span = m.end() - m.start()
                # Cleanup the args_only string by removing the parentheses and
                # their content.
                args_only = args_only.replace(m.group(), "")

        # Now we are trying to split the args_only string in multiple arguments
        previous_found, found = 0, 0
        while True:
            found = self.__find_args_separator(args_only, previous_found)
            if -1 == found:
                args.append(args_only[previous_found:].strip())
                # This is the last argument. Break out of the loop.
                break
            else:
                args.append(args_only[previous_found: found].strip())
            previous_found = found + 1  # skip found separator

        # Get the size and position for each argument
        absolute_pos_list = []
        absolute_pos = 0
        for arg in args:
            absolute_pos += len(arg)
            absolute_pos_list.append(absolute_pos)

        for item in parentheses_blocks:
            # In case where there are parentheses blocks we add them back
            # to the right argument
            parentheses_block_absolute_pos = item[0]
            parentheses_block_string = item[1]

            current_arg_absolute_pos = 0
            for arg_index, arg_absolute_pos in enumerate(absolute_pos_list):
                current_arg_absolute_pos += arg_absolute_pos
                if current_arg_absolute_pos >= parentheses_block_absolute_pos:
                    # Add the parentheses block back and break out of the loop.
                    args[arg_index] += parentheses_block_string
                    break

        return args

    NOT_FOUND = (-1, -1)
    """implementation details"""

    def find_args(self, text, start=None):
        """implementation details"""
        if start is None:
            start = 0
        first_occurance = text.find(self.__begin, start)
        if first_occurance == -1:
            return self.NOT_FOUND
        previous_found, found = first_occurance + 1, 0
        while True:
            found = self.__find_args_separator(text, previous_found)
            if -1 == found:
                return self.NOT_FOUND
            elif text[found] == self.__end:
                return first_occurance, found
            else:
                previous_found = found + 1  # skip found sep

    def split(self, decl_string):
        """implementation details"""
        assert self.has_pattern(decl_string)
        return self.name(decl_string), self.args(decl_string)

    def split_recursive(self, decl_string):
        """implementation details"""
        assert self.has_pattern(decl_string)
        answer = []
        to_go = [decl_string]
        while to_go:
            name, args = self.split(to_go.pop())
            answer.append((name, args))
            for arg in args:
                if self.has_pattern(arg):
                    to_go.append(arg)
        return answer

    def join(self, name, args, arg_separator=None):
        """implementation details"""
        if None is arg_separator:
            arg_separator = ', '
        args = [_f for _f in args if _f]

        if not args:
            args_str = ' '
        elif 1 == len(args):
            args_str = ' ' + args[0] + ' '
        else:
            args_str = ' ' + arg_separator.join(args) + ' '

        return ''.join([name, self.__begin, args_str, self.__end])

    def normalize(self, decl_string, arg_separator=None):
        """implementation details"""
        if not self.has_pattern(decl_string):
            return decl_string
        name, args = self.split(decl_string)
        for i, arg in enumerate(args):
            args[i] = self.normalize(arg)
        return self.join(name, args, arg_separator)