diff options
| author | Ben Sanders <ben@sanders.life> | 2026-08-02 09:49:25 -0400 |
|---|---|---|
| committer | Ben Sanders <ben@sanders.life> | 2026-08-02 09:49:25 -0400 |
| commit | b41479c91e6685511c1f8ba8586106b322073b62 (patch) | |
| tree | c9f1345999d754ae0a533849966427e792d9e68d /vendor/bundle/ruby/3.4.0/gems/ffi-1.17.4-arm64-darwin/lib/ffi/tools | |
| parent | cfaceeb9a6d1295f5754be211858155cd309acc2 (diff) | |
added statscounter code
Diffstat (limited to 'vendor/bundle/ruby/3.4.0/gems/ffi-1.17.4-arm64-darwin/lib/ffi/tools')
4 files changed, 564 insertions, 0 deletions
diff --git a/vendor/bundle/ruby/3.4.0/gems/ffi-1.17.4-arm64-darwin/lib/ffi/tools/const_generator.rb b/vendor/bundle/ruby/3.4.0/gems/ffi-1.17.4-arm64-darwin/lib/ffi/tools/const_generator.rb new file mode 100644 index 0000000..70ba9c2 --- /dev/null +++ b/vendor/bundle/ruby/3.4.0/gems/ffi-1.17.4-arm64-darwin/lib/ffi/tools/const_generator.rb @@ -0,0 +1,232 @@ +require 'tempfile' +require 'open3' + +module FFI + + # ConstGenerator turns C constants into ruby values. + # + # @example a simple example for stdio + # require 'ffi/tools/const_generator' + # 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_path = nil + + Tempfile.open("#{@prefix}.const_generator") do |f| + binary_path = f.path + ".bin" + @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 + + cc = ENV['CC'] || 'gcc' + output = `#{cc} #{options[:cppflags]} -D_DARWIN_USE_64_BIT_INODE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -x c -Wall -Werror #{f.path} -o #{binary_path} 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_path}` + File.unlink(binary_path + (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 diff --git a/vendor/bundle/ruby/3.4.0/gems/ffi-1.17.4-arm64-darwin/lib/ffi/tools/generator.rb b/vendor/bundle/ruby/3.4.0/gems/ffi-1.17.4-arm64-darwin/lib/ffi/tools/generator.rb new file mode 100644 index 0000000..5552ea5 --- /dev/null +++ b/vendor/bundle/ruby/3.4.0/gems/ffi-1.17.4-arm64-darwin/lib/ffi/tools/generator.rb @@ -0,0 +1,105 @@ +require 'ffi/tools/struct_generator' +require 'ffi/tools/const_generator' + +module FFI + + ## + # Generate files with C structs for FFI::Struct and C constants. + # + # == A simple example + # + # In file +zlib.rb.ffi+: + # module Zlib + # @@@ + # constants do |c| + # c.include "zlib.h" + # c.const :ZLIB_VERNUM + # end + # @@@ + # + # class ZStream < FFI::Struct + # + # struct do |s| + # s.name "struct z_stream_s" + # s.include "zlib.h" + # + # s.field :next_in, :pointer + # s.field :avail_in, :uint + # s.field :total_in, :ulong + # end + # @@@ + # end + # end + # + # Translate the file: + # require "ffi/tools/generator" + # FFI::Generator.new "zlib.rb.ffi", "zlib.rb" + # + # Generates the file +zlib.rb+ with constant values and offsets: + # module Zlib + # ZLIB_VERNUM = 4784 + # + # class ZStream < FFI::Struct + # layout :next_in, :pointer, 0, + # :avail_in, :uint, 8, + # :total_in, :ulong, 16 + # end + # + # @see FFI::Generator::Task for easy integration in a Rakefile + class Generator + + def initialize(ffi_name, rb_name, options = {}) + @ffi_name = ffi_name + @rb_name = rb_name + @options = options + @name = File.basename rb_name, '.rb' + + file = File.read @ffi_name + + new_file = file.gsub(/^( *)@@@(.*?)@@@/m) do + @constants = [] + @structs = [] + + indent = $1 + original_lines = $2.count "\n" + + instance_eval $2, @ffi_name, $`.count("\n") + + new_lines = [] + @constants.each { |c| new_lines << c.to_ruby } + @structs.each { |s| new_lines << s.generate_layout } + + new_lines = new_lines.join("\n").split "\n" # expand multiline blocks + new_lines = new_lines.map { |line| indent + line } + + padding = original_lines - new_lines.length + new_lines += [nil] * padding if padding >= 0 + + new_lines.join "\n" + end + + open @rb_name, 'w' do |f| + f.puts "# This file is generated from `#{@ffi_name}'. Do not edit." + f.puts + f.puts new_file + end + end + + def constants(options = {}, &block) + @constants << FFI::ConstGenerator.new(@name, @options.merge(options), &block) + end + + def struct(options = {}, &block) + @structs << FFI::StructGenerator.new(@name, @options.merge(options), &block) + end + + ## + # Utility converter for constants + + def to_s + proc { |obj| obj.to_s.inspect } + end + + end +end + diff --git a/vendor/bundle/ruby/3.4.0/gems/ffi-1.17.4-arm64-darwin/lib/ffi/tools/generator_task.rb b/vendor/bundle/ruby/3.4.0/gems/ffi-1.17.4-arm64-darwin/lib/ffi/tools/generator_task.rb new file mode 100644 index 0000000..da72968 --- /dev/null +++ b/vendor/bundle/ruby/3.4.0/gems/ffi-1.17.4-arm64-darwin/lib/ffi/tools/generator_task.rb @@ -0,0 +1,32 @@ +require 'ffi/tools/generator' +require 'rake' +require 'rake/tasklib' + +## +# Add Rake tasks that generate files with C structs for FFI::Struct and C constants. +# +# @example a simple example for your Rakefile +# require "ffi/tools/generator_task" +# # Add a task to generate my_object.rb out of my_object.rb.ffi +# FFI::Generator::Task.new ["my_object.rb"], cflags: "-I/usr/local/mylibrary" +# +# The generated files are also added to the 'clear' task. +# +# @see FFI::Generator for a description of the file content +class FFI::Generator::Task < Rake::TaskLib + + def initialize(rb_names, options={}) + task :clean do rm_f rb_names end + + rb_names.each do |rb_name| + ffi_name = "#{rb_name}.ffi" + + file rb_name => ffi_name do |t| + puts "Generating #{rb_name}..." if Rake.application.options.trace + + FFI::Generator.new ffi_name, rb_name, options + end + end + end + +end diff --git a/vendor/bundle/ruby/3.4.0/gems/ffi-1.17.4-arm64-darwin/lib/ffi/tools/struct_generator.rb b/vendor/bundle/ruby/3.4.0/gems/ffi-1.17.4-arm64-darwin/lib/ffi/tools/struct_generator.rb new file mode 100644 index 0000000..3a951c3 --- /dev/null +++ b/vendor/bundle/ruby/3.4.0/gems/ffi-1.17.4-arm64-darwin/lib/ffi/tools/struct_generator.rb @@ -0,0 +1,195 @@ +require 'tempfile' + +module FFI + + ## + # Generates an FFI Struct layout. + # + # Given the @@@ portion in: + # + # class Zlib::ZStream < FFI::Struct + # @@@ + # name "struct z_stream_s" + # include "zlib.h" + # + # field :next_in, :pointer + # field :avail_in, :uint + # field :total_in, :ulong + # + # # ... + # @@@ + # end + # + # StructGenerator will create the layout: + # + # layout :next_in, :pointer, 0, + # :avail_in, :uint, 4, + # :total_in, :ulong, 8, + # # ... + # + # StructGenerator does its best to pad the layout it produces to preserve + # line numbers. Place the struct definition as close to the top of the file + # for best results. + + class StructGenerator + @options = {} + attr_accessor :size + attr_reader :fields + + def initialize(name, options = {}) + @name = name + @struct_name = nil + @includes = [] + @fields = [] + @found = false + @size = nil + + if block_given? then + yield self + calculate self.class.options.merge(options) + end + end + def self.options=(options) + @options = options + end + def self.options + @options + end + def calculate(options = {}) + binary = File.join Dir.tmpdir, "rb_struct_gen_bin_#{Process.pid}" + + raise "struct name not set" if @struct_name.nil? + + Tempfile.open("#{@name}.struct_generator") do |f| + f.puts "#include <stdio.h>" + + @includes.each do |inc| + f.puts "#include <#{inc}>" + end + + f.puts "#include <stddef.h>\n\n" + f.puts "int main(int argc, char **argv)\n{" + f.puts " #{@struct_name} s;" + f.puts %[ printf("sizeof(#{@struct_name}) %u\\n", (unsigned int) sizeof(#{@struct_name}));] + + @fields.each do |field| + f.puts <<-EOF + printf("#{field.name} %u %u\\n", (unsigned int) offsetof(#{@struct_name}, #{field.name}), + (unsigned int) sizeof(s.#{field.name})); + EOF + end + + f.puts "\n return 0;\n}" + f.flush + + cc = ENV['CC'] || 'gcc' + output = `#{cc} #{options[:cppflags]} #{options[:cflags]} -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 + @found = false + output = output.split("\n").map { |l| "\t#{l}" }.join "\n" + raise "Compilation error generating struct #{@name} (#{@struct_name}):\n#{output}" + end + end + + output = `#{binary}`.split "\n" + File.unlink(binary + (FFI::Platform.windows? ? ".exe" : "")) + sizeof = output.shift + unless @size + m = /\s*sizeof\([^)]+\) (\d+)/.match sizeof + @size = m[1] + end + + line_no = 0 + output.each do |line| + md = line.match(/.+ (\d+) (\d+)/) + @fields[line_no].offset = md[1].to_i + @fields[line_no].size = md[2].to_i + + line_no += 1 + end + + @found = true + end + + def field(name, type=nil) + field = Field.new(name, type) + @fields << field + return field + end + + def found? + @found + end + + def dump_config(io) + io.puts "rbx.platform.#{@name}.sizeof = #{@size}" + + @fields.each { |field| io.puts field.to_config(@name) } + end + + def generate_layout + buf = "" + + @fields.each_with_index do |field, i| + if buf.empty? + buf << "layout :#{field.name}, :#{field.type}, #{field.offset}" + else + buf << " :#{field.name}, :#{field.type}, #{field.offset}" + end + + if i < @fields.length - 1 + buf << ",\n" + end + end + + buf + end + + def get_field(name) + @fields.find { |f| name == f.name } + end + + def include(i) + @includes << i + end + + def name(n) + @struct_name = n + end + + end + + ## + # A field in a Struct. + + class StructGenerator::Field + + attr_reader :name + attr_reader :type + attr_reader :offset + attr_accessor :size + + def initialize(name, type) + @name = name + @type = type + @offset = nil + @size = nil + end + + def offset=(o) + @offset = o + end + + def to_config(name) + buf = [] + buf << "rbx.platform.#{name}.#{@name}.offset = #{@offset}" + buf << "rbx.platform.#{name}.#{@name}.size = #{@size}" + buf << "rbx.platform.#{name}.#{@name}.type = #{@type}" if @type + buf + end + + end + +end + |
