This file is indexed.

/usr/lib/ruby/vendor_ruby/ffi/tools/const_generator.rb is in ruby-ffi 1.9.10debian-1build2.

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
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
require 'tempfile'
require 'open3'

module FFI

  # ConstGenerator turns C constants into ruby values.
  #
  # @example a simple example for stdio
  #  cg = FFI::ConstGenerator.new('stdio') do |gen|
  #    gen.const(:SEEK_SET)
  #    gen.const('SEEK_CUR')
  #    gen.const('seek_end')   # this constant does not exist
  #  end            # #calculate called automatically at the end of the block
  #
  #  cg['SEEK_SET'] # => 0
  #  cg['SEEK_CUR'] # => 1
  #  cg['seek_end'] # => nil
  #  cg.to_ruby     # => "SEEK_SET = 0\nSEEK_CUR = 1\n# seek_end not available"
  class ConstGenerator
    @options = {}
    attr_reader :constants

    # Creates a new constant generator that uses +prefix+ as a name, and an
    # options hash.
    #
    # The only option is +:required+, which if set to +true+ raises an error if a
    # constant you have requested was not found.
    # 
    # @param [#to_s] prefix
    # @param [Hash] options
    # @return 
    # @option options [Boolean] :required
    # @overload initialize(prefix, options)
    # @overload initialize(prefix, options) { |gen| ... }
    #  @yieldparam [ConstGenerator] gen new generator is passed to the block
    #  When passed a block, {#calculate} is automatically called at the end of
    #  the block, otherwise you must call it yourself.
    def initialize(prefix = nil, options = {})
      @includes = ['stdio.h', 'stddef.h']
      @constants = {}
      @prefix = prefix

      @required = options[:required]
      @options = options

      if block_given? then
        yield self
        calculate self.class.options.merge(options)
      end
    end
    # Set class options
    # These options are merged with {#initialize} options when it is called with a block.
    # @param [Hash] options
    # @return [Hash] class options
    def self.options=(options)
      @options = options
    end
    # Get class options.
    # @return [Hash] class options
    def self.options
      @options
    end
    # @param [String] name
    # @return constant value (converted if a +converter+ was defined).
    # Access a constant by name.
    def [](name)
      @constants[name].converted_value
    end

    # Request the value for C constant +name+.
    #
    # @param [#to_s] name C constant name
    # @param [String] format a printf format string to print the value out
    # @param [String] cast a C cast for the value
    # @param ruby_name alternate ruby name for {#to_ruby}
    #
    # @overload const(name, format=nil, cast='', ruby_name=nil, converter=nil)
    #  +converter+ is a Method or a Proc.
    #  @param [#call] converter convert the value from a string to the appropriate
    #   type for {#to_ruby}.
    # @overload const(name, format=nil, cast='', ruby_name=nil) { |value| ... }
    #  Use a converter block. This block convert the value from a string to the 
    #  appropriate type for {#to_ruby}.
    #  @yieldparam value constant value
    def const(name, format = nil, cast = '', ruby_name = nil, converter = nil,
              &converter_proc)
      format ||= '%d'
      cast ||= ''

      if converter_proc and converter then
        raise ArgumentError, "Supply only converter or converter block"
      end

      converter = converter_proc if converter.nil?

      const = Constant.new name, format, cast, ruby_name, converter
      @constants[name.to_s] = const
      return const
    end

    # Calculate constants values.
    # @param [Hash] options
    # @option options [String] :cppflags flags for C compiler
    # @return [nil]
    # @raise if a constant is missing and +:required+ was set to +true+ (see {#initialize})
    def calculate(options = {})
      binary = File.join Dir.tmpdir, "rb_const_gen_bin_#{Process.pid}"

      Tempfile.open("#{@prefix}.const_generator") do |f|
        @includes.each do |inc|
          f.puts "#include <#{inc}>"
        end
        f.puts "\nint main(int argc, char **argv)\n{"

        @constants.each_value do |const|
          f.puts <<-EOF
  #ifdef #{const.name}
  printf("#{const.name} #{const.format}\\n", #{const.cast}#{const.name});
  #endif
          EOF
        end

        f.puts "\n\treturn 0;\n}"
        f.flush

        output = `gcc #{options[:cppflags]} -D_DARWIN_USE_64_BIT_INODE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -x c -Wall -Werror #{f.path} -o #{binary} 2>&1`

        unless $?.success? then
          output = output.split("\n").map { |l| "\t#{l}" }.join "\n"
          raise "Compilation error generating constants #{@prefix}:\n#{output}"
        end
      end

      output = `#{binary}`
      File.unlink(binary + (FFI::Platform.windows? ? ".exe" : ""))
      output.each_line do |line|
        line =~ /^(\S+)\s(.*)$/
        const = @constants[$1]
        const.value = $2
      end

      missing_constants = @constants.select do |name, constant|
        constant.value.nil?
      end.map { |name,| name }

      if @required and not missing_constants.empty? then
        raise "Missing required constants for #{@prefix}: #{missing_constants.join ', '}"
      end
    end

    # Dump constants to +io+.
    # @param [#puts] io
    # @return [nil]
    def dump_constants(io)
      @constants.each do |name, constant|
        name = [@prefix, name].join '.' if @prefix
        io.puts "#{name} = #{constant.converted_value}"
      end
    end

    # Outputs values for discovered constants.  If the constant's value was
    # not discovered it is not omitted.
    # @return [String]
    def to_ruby
      @constants.sort_by { |name,| name }.map do |name, constant|
        if constant.value.nil? then
          "# #{name} not available"
        else
          constant.to_ruby
        end
      end.join "\n"
    end

    # Add additional C include file(s) to calculate constants from.
    # @note +stdio.h+ and +stddef.h+ automatically included
    # @param [List<String>, Array<String>] i include file(s)
    # @return [Array<String>] array of include files
    def include(*i)
      @includes |= i.flatten
    end

  end

  # This class hold constants for {ConstGenerator}
  class ConstGenerator::Constant

    attr_reader :name, :format, :cast
    attr_accessor :value

    # @param [#to_s] name
    # @param [String] format a printf format string to print the value out
    # @param [String] cast a C cast for the value
    # @param ruby_name alternate ruby name for {#to_ruby}
    # @param [#call] converter convert the value from a string to the appropriate
    #  type for {#to_ruby}.
    def initialize(name, format, cast, ruby_name = nil, converter=nil)
      @name = name
      @format = format
      @cast = cast
      @ruby_name = ruby_name
      @converter = converter
      @value = nil
    end

    # Return constant value (converted if a +converter+ was defined).
    # @return constant value.
    def converted_value
      if @converter
        @converter.call(@value)
      else
        @value
      end
    end

    # get constant ruby name
    # @return [String]
    def ruby_name
      @ruby_name || @name
    end

    # Get an evaluable string from constant.
    # @return [String]
    def to_ruby
      "#{ruby_name} = #{converted_value}"
    end

  end  

end