sender 1.4.3 → 1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +14 -0
- data/Makefile +1 -1
- data/README.rdoc +232 -106
- data/Rakefile +1 -1
- data/VERSION.rdoc +1 -1
- data/ext/sender/RPSender_internal.h +5 -0
- data/ext/sender/RubySourceSupport.c +13 -8
- data/ext/sender/RubySourceSupport.h +62 -1
- data/ext/sender/rb_Kernel.c +454 -44
- data/ext/sender/rb_Kernel.h +14 -1
- data/lib/VERSION.rdoc +1 -1
- data/lib/sender/sender.bundle +0 -0
- data/sender.gemspec +8 -6
- metadata +10 -9
    
        data/CHANGELOG.rdoc
    CHANGED
    
    | @@ -40,3 +40,17 @@ Fixed path problem for VERSION.rdoc. | |
| 40 40 | 
             
            === 1.4.3 2010-06-29
         | 
| 41 41 |  | 
| 42 42 | 
             
            Fixed problems with superclass method definitions so __sender__ and __caller__ return the caller to the first method in the class chain.
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            === 1.5 2010-07-09
         | 
| 45 | 
            +
             | 
| 46 | 
            +
            Added to Kernel:
         | 
| 47 | 
            +
            * :each_backtrace_frame
         | 
| 48 | 
            +
            * :backtrace_includes?
         | 
| 49 | 
            +
            * :backtrace_includes_one_of?
         | 
| 50 | 
            +
            * :backtrace_frame_with
         | 
| 51 | 
            +
            * :backtrace_frames_with
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            Added Hash-specification support for context inspection. Now functions take element value (object instance, class, method symbol, filename string,
         | 
| 54 | 
            +
            line number fixnum) or Hash containing frame detail specification. 
         | 
| 55 | 
            +
             | 
| 56 | 
            +
            Added Enumerator support. Non-block enumeration will iterate the backtrace that was the active context when :each_backtrace_frame was called.
         | 
    
        data/Makefile
    CHANGED
    
    | @@ -53,7 +53,7 @@ COUTFLAG = -o | |
| 53 53 | 
             
            RUBY_EXTCONF_H = 
         | 
| 54 54 | 
             
            cflags   = $(optflags) $(debugflags) $(warnflags)
         | 
| 55 55 | 
             
            optflags = 
         | 
| 56 | 
            -
            debugflags = - | 
| 56 | 
            +
            debugflags = -g3  
         | 
| 57 57 | 
             
            warnflags = -Wall -Wno-parentheses
         | 
| 58 58 | 
             
            CFLAGS   =  -fno-common  $(cflags)  -fno-common -pipe -fno-common 
         | 
| 59 59 | 
             
            INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir) -I/usr/src/ruby
         | 
    
        data/README.rdoc
    CHANGED
    
    | @@ -4,9 +4,11 @@ http://rubygems.org/gems/sender | |
| 4 4 |  | 
| 5 5 | 
             
            == DESCRIPTION:
         | 
| 6 6 |  | 
| 7 | 
            -
            Adds :__sender__ and :__caller__ to the built-in :__callee__ and :__method__ methods in Ruby 1.9.1 | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 7 | 
            +
            Adds :__sender__ and :__caller__ to the built-in :__callee__ and :__method__ methods in Ruby 1.9.1.
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            Also provides object-oriented :backtrace supporting n-levels backward, :each_backtrace_frame for iteration, :backtrace_includes?, 
         | 
| 10 | 
            +
            and :backtrace_includes_one_of? for context inspection, and :backtrace_frame_with and :backtrace_frames_with, which return
         | 
| 11 | 
            +
            matching frame information for the frame(s) matching the given description.
         | 
| 10 12 |  | 
| 11 13 | 
             
            == SUMMARY:
         | 
| 12 14 |  | 
| @@ -17,10 +19,14 @@ which allows contents of the backtrace to be queried. | |
| 17 19 | 
             
            	* __caller__
         | 
| 18 20 | 
             
            	* backtrace
         | 
| 19 21 | 
             
            	* backtrace( frames_to_trace_backward )
         | 
| 20 | 
            -
            	* backtrace_includes?( Class )
         | 
| 21 | 
            -
            	* backtrace_includes?( class_instance )
         | 
| 22 | 
            -
            	*  | 
| 23 | 
            -
            	*  | 
| 22 | 
            +
            	* backtrace_includes?( Class, class_instance, :symbol, {frame_hash}, ... )
         | 
| 23 | 
            +
            	* backtrace_includes?( frames_to_trace_backward, Class, class_instance, :symbol, {frame_hash}, ... )
         | 
| 24 | 
            +
            	* backtrace_includes_one_of?( Class, class_instance, :symbol, {frame_hash}, ... )
         | 
| 25 | 
            +
            	* backtrace_includes_one_of?( frames_to_trace_backward, Class, class_instance, :symbol, {frame_hash}, ... )
         | 
| 26 | 
            +
            	* backtrace_frame_with( Class, class_instance, :symbol, {frame_hash}, ... )
         | 
| 27 | 
            +
            	* backtrace_frame_with( frames_to_trace_backward, Class, class_instance, :symbol, {frame_hash}, ... )
         | 
| 28 | 
            +
            	* backtrace_frames_with( Class, class_instance, :symbol, {frame_hash}, ... )
         | 
| 29 | 
            +
            	* backtrace_frames_with( frames_to_trace_backward, Class, class_instance, :symbol, {frame_hash}, ... )
         | 
| 24 30 |  | 
| 25 31 | 
             
            == INSTALL:
         | 
| 26 32 |  | 
| @@ -29,73 +35,103 @@ which allows contents of the backtrace to be queried. | |
| 29 35 | 
             
            == EXAMPLE:
         | 
| 30 36 |  | 
| 31 37 | 
             
            	require 'sender'
         | 
| 32 | 
            -
             | 
| 33 38 | 
             
            	require 'pp'
         | 
| 34 39 |  | 
| 35 40 | 
             
            	class Test
         | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
             | 
| 46 | 
            -
             | 
| 47 | 
            -
             | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
             | 
| 52 | 
            -
             | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
             | 
| 56 | 
            -
             | 
| 57 | 
            -
             | 
| 58 | 
            -
             | 
| 59 | 
            -
             | 
| 41 | 
            +
             | 
| 42 | 
            +
            		def initialize
         | 
| 43 | 
            +
            			puts 'In method <Test>:initialize'
         | 
| 44 | 
            +
            			puts 'Sender was: ' + __sender__.pretty_inspect.to_s
         | 
| 45 | 
            +
            			puts 'Caller was: ' + __caller__.to_s
         | 
| 46 | 
            +
            		end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
            		def test
         | 
| 49 | 
            +
            			puts 'In <Test>:test'
         | 
| 50 | 
            +
            			self.another_test
         | 
| 51 | 
            +
            		end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            		def another_test
         | 
| 54 | 
            +
            			puts 'In method <Test>:another_test'
         | 
| 55 | 
            +
            			test2 = Test2.new
         | 
| 56 | 
            +
            			test2.and_another_test_in_another_object
         | 
| 57 | 
            +
            		end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
            		def and_another_test_in_another_object
         | 
| 60 | 
            +
            			puts 'In method <Test>:and_another_test_in_another_object'
         | 
| 61 | 
            +
            			puts 'Sender was: ' + __sender__.pretty_inspect.to_s
         | 
| 62 | 
            +
            			puts 'Caller was: ' + __caller__.to_s
         | 
| 63 | 
            +
            		end
         | 
| 64 | 
            +
             | 
| 60 65 | 
             
            	end
         | 
| 61 66 |  | 
| 62 67 | 
             
            	class Test2 < Test
         | 
| 63 | 
            -
              
         | 
| 64 | 
            -
            	  def initialize
         | 
| 65 | 
            -
            	    puts 'In method <Test2>:initialize'
         | 
| 66 | 
            -
            	    super
         | 
| 67 | 
            -
            	    puts 'Sender was: ' + __sender__.pretty_inspect.to_s
         | 
| 68 | 
            -
            	    puts 'Caller was: ' + __caller__.to_s
         | 
| 69 | 
            -
            	    pp Kernel.backtrace
         | 
| 70 | 
            -
            	  end
         | 
| 71 | 
            -
              
         | 
| 72 | 
            -
            	  def and_another_test_in_another_object
         | 
| 73 | 
            -
            	    puts 'In method <Test2>:and_another_test_in_another_object'
         | 
| 74 | 
            -
            	    super
         | 
| 75 | 
            -
            	    pp self
         | 
| 76 | 
            -
            	    puts 'Sender was: ' + __sender__.pretty_inspect.to_s
         | 
| 77 | 
            -
            	    puts 'Caller was: ' + __caller__.to_s
         | 
| 78 | 
            -
            	    pp Kernel.backtrace    
         | 
| 79 | 
            -
            	    pp Kernel.backtrace( 2 )
         | 
| 80 | 
            -
            	    puts 'These should be true:'
         | 
| 81 | 
            -
            	    pp Kernel.backtrace_includes?( :another_test )
         | 
| 82 | 
            -
            	    pp Kernel.backtrace_includes?( Test )
         | 
| 83 | 
            -
            	    pp Kernel.backtrace_includes?( $test )
         | 
| 84 | 
            -
            	    pp Kernel.backtrace_includes?( :another_test, Test, $test )
         | 
| 85 | 
            -
            	    puts 'These should be false:'
         | 
| 86 | 
            -
            	    pp Kernel.backtrace_includes?( :yet_another_test )
         | 
| 87 | 
            -
            	    pp Kernel.backtrace_includes?( Test2 )
         | 
| 88 | 
            -
            	    pp Kernel.backtrace_includes?( self )
         | 
| 89 | 
            -
            	    pp Kernel.backtrace_includes?( :yet_another_test, Test2, self )
         | 
| 90 | 
            -
            	  end
         | 
| 91 | 
            -
              
         | 
| 92 | 
            -
            	end
         | 
| 93 68 |  | 
| 94 | 
            -
             | 
| 95 | 
            -
             | 
| 69 | 
            +
            		def initialize
         | 
| 70 | 
            +
            			puts 'In method <Test2>:initialize'
         | 
| 71 | 
            +
            			super
         | 
| 72 | 
            +
            			puts 'Sender was: ' + __sender__.pretty_inspect.to_s
         | 
| 73 | 
            +
            			puts 'Caller was: ' + __caller__.to_s
         | 
| 74 | 
            +
            			pp Kernel.backtrace
         | 
| 75 | 
            +
            		end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
            		def and_another_test_in_another_object
         | 
| 78 | 
            +
            			puts 'In method <Test2>:and_another_test_in_another_object'
         | 
| 79 | 
            +
            			super
         | 
| 80 | 
            +
            			pp self
         | 
| 81 | 
            +
            			puts 'Sender was: ' + __sender__.pretty_inspect.to_s
         | 
| 82 | 
            +
            			puts 'Caller was: ' + __caller__.to_s
         | 
| 83 | 
            +
            			pp Kernel.backtrace		
         | 
| 84 | 
            +
            			pp Kernel.backtrace( 2 )
         | 
| 85 | 
            +
            			puts 'These should be true:'
         | 
| 86 | 
            +
            			pp Kernel.backtrace_includes?( :another_test )
         | 
| 87 | 
            +
            			pp Kernel.backtrace_includes?( Test )
         | 
| 88 | 
            +
            			pp Kernel.backtrace_includes?( $test )
         | 
| 89 | 
            +
            			pp Kernel.backtrace_includes?( :another_test, Test, $test )
         | 
| 90 | 
            +
            			pp Kernel.backtrace_includes?( "sender_test.rb" )
         | 
| 91 | 
            +
            			puts 'These should be false:'
         | 
| 92 | 
            +
            			pp Kernel.backtrace_includes?( :yet_another_test )
         | 
| 93 | 
            +
            			pp Kernel.backtrace_includes?( Test2 )
         | 
| 94 | 
            +
            			pp Kernel.backtrace_includes?( self )
         | 
| 95 | 
            +
            			pp Kernel.backtrace_includes?( :yet_another_test, Test2, self )
         | 
| 96 | 
            +
            			pp Kernel.backtrace_includes?( "sender_test.rbi" )
         | 
| 97 | 
            +
             | 
| 98 | 
            +
            			puts 'And now we get a step by step backtrace'
         | 
| 99 | 
            +
            			which_step = 1
         | 
| 100 | 
            +
            			Kernel.each_backtrace_frame do |this_frame|
         | 
| 101 | 
            +
            				puts 'Frame number ' + which_step.to_s + ':'
         | 
| 102 | 
            +
            				pp this_frame
         | 
| 103 | 
            +
            				which_step += 1
         | 
| 104 | 
            +
            			end
         | 
| 105 | 
            +
            			puts 'And now we try a backtrace inside a block.'
         | 
| 106 | 
            +
            			block_item = [ 'one_item' ]
         | 
| 107 | 
            +
            			block_item.each do |this_item|
         | 
| 108 | 
            +
            				pp Kernel.backtrace
         | 
| 109 | 
            +
            			end
         | 
| 96 110 |  | 
| 97 | 
            -
             | 
| 98 | 
            -
             | 
| 111 | 
            +
            			puts 'And :backtrace_includes_one_of?; this should be true:'
         | 
| 112 | 
            +
            			pp Kernel.backtrace_includes_one_of?( :some_method_that_does_not_exit, :another_test, :test, :some_other_test_that_does_not_exist )
         | 
| 113 | 
            +
            			puts 'as should this:'
         | 
| 114 | 
            +
            			pp Kernel.backtrace_includes_one_of?( { :method => :another_test, :object => $test }, { :method => :test } )
         | 
| 115 | 
            +
             | 
| 116 | 
            +
            			puts 'And :backtrace_frame_with; this should be a Hash:'
         | 
| 117 | 
            +
            			pp Kernel.backtrace_frame_with( :test )
         | 
| 118 | 
            +
            			puts 'as should this:'
         | 
| 119 | 
            +
            			pp Kernel.backtrace_frame_with( "sender_test.rb" )
         | 
| 120 | 
            +
             | 
| 121 | 
            +
            			puts 'And :backtrace_frames_with; this should be an Array of Hashes'
         | 
| 122 | 
            +
            			pp Kernel.backtrace_frames_with( :object => $test )
         | 
| 123 | 
            +
            			puts 'as should this:'
         | 
| 124 | 
            +
            			pp Kernel.backtrace_frames_with( :file => "sender_test.rb" )
         | 
| 125 | 
            +
             | 
| 126 | 
            +
            		    puts 'And try iterating with an Enumerator'
         | 
| 127 | 
            +
            		    enumerator = Kernel.each_backtrace_frame
         | 
| 128 | 
            +
            		    pp enumerator
         | 
| 129 | 
            +
            		    while result = enumerator.next
         | 
| 130 | 
            +
            		      pp result
         | 
| 131 | 
            +
            		    end
         | 
| 132 | 
            +
             | 
| 133 | 
            +
            		end
         | 
| 134 | 
            +
            	end
         | 
| 99 135 |  | 
| 100 136 | 
             
            == EXAMPLE's OUTPUT:
         | 
| 101 137 |  | 
| @@ -106,65 +142,155 @@ which allows contents of the backtrace to be queried. | |
| 106 142 | 
             
            	In method <Test>:another_test
         | 
| 107 143 | 
             
            	In method <Test2>:initialize
         | 
| 108 144 | 
             
            	In method <Test>:initialize
         | 
| 109 | 
            -
            	Sender was: #<Test: | 
| 145 | 
            +
            	Sender was: #<Test:0x0000010081ba10>
         | 
| 110 146 | 
             
            	Caller was: another_test
         | 
| 111 | 
            -
            	Sender was: #<Test: | 
| 147 | 
            +
            	Sender was: #<Test:0x0000010081ba10>
         | 
| 112 148 | 
             
            	Caller was: another_test
         | 
| 113 | 
            -
            	[{:object=>#<Test2: | 
| 114 | 
            -
             | 
| 115 | 
            -
             | 
| 116 | 
            -
             | 
| 149 | 
            +
            	[{:object=>#<Test2:0x0000010081a7e8>,
         | 
| 150 | 
            +
            		:file=>"sender_test.rb",
         | 
| 151 | 
            +
            		:line=>39,
         | 
| 152 | 
            +
            		:method=>:initialize},
         | 
| 117 153 | 
             
            	 {:object=>Test2, :file=>nil, :line=>nil, :method=>:new},
         | 
| 118 | 
            -
            	 {:object=>#<Test: | 
| 119 | 
            -
             | 
| 120 | 
            -
             | 
| 121 | 
            -
             | 
| 122 | 
            -
            	 {:object=>#<Test: | 
| 123 | 
            -
             | 
| 124 | 
            -
             | 
| 125 | 
            -
             | 
| 126 | 
            -
            	 {:object=>main, :file=>"sender_test.rb", :line=> | 
| 154 | 
            +
            	 {:object=>#<Test:0x0000010081ba10>,
         | 
| 155 | 
            +
            		:file=>"sender_test.rb",
         | 
| 156 | 
            +
            		:line=>20,
         | 
| 157 | 
            +
            		:method=>:another_test},
         | 
| 158 | 
            +
            	 {:object=>#<Test:0x0000010081ba10>,
         | 
| 159 | 
            +
            		:file=>"sender_test.rb",
         | 
| 160 | 
            +
            		:line=>15,
         | 
| 161 | 
            +
            		:method=>:test},
         | 
| 162 | 
            +
            	 {:object=>main, :file=>"sender_test.rb", :line=>96, :method=>:"<main>"},
         | 
| 127 163 | 
             
            	 {:object=>main, :file=>"<main>", :line=>0, :method=>:"<main>"}]
         | 
| 128 164 | 
             
            	In method <Test2>:and_another_test_in_another_object
         | 
| 129 165 | 
             
            	In method <Test>:and_another_test_in_another_object
         | 
| 130 | 
            -
            	 | 
| 131 | 
            -
            	Sender was: #<Test2:0x00000100823030>
         | 
| 166 | 
            +
            	Sender was: #<Test2:0x0000010081a7e8>
         | 
| 132 167 | 
             
            	Caller was: another_test
         | 
| 133 | 
            -
            	#<Test2: | 
| 134 | 
            -
            	Sender was: #<Test: | 
| 168 | 
            +
            	#<Test2:0x0000010081a7e8>
         | 
| 169 | 
            +
            	Sender was: #<Test:0x0000010081ba10>
         | 
| 135 170 | 
             
            	Caller was: another_test
         | 
| 136 | 
            -
            	[{:object=>#<Test2: | 
| 137 | 
            -
             | 
| 138 | 
            -
             | 
| 139 | 
            -
             | 
| 140 | 
            -
            	 {:object=>#<Test: | 
| 141 | 
            -
             | 
| 142 | 
            -
             | 
| 143 | 
            -
             | 
| 144 | 
            -
            	 {:object=>#<Test: | 
| 145 | 
            -
             | 
| 146 | 
            -
             | 
| 147 | 
            -
             | 
| 148 | 
            -
            	 {:object=>main, :file=>"sender_test.rb", :line=> | 
| 171 | 
            +
            	[{:object=>#<Test2:0x0000010081a7e8>,
         | 
| 172 | 
            +
            		:file=>"sender_test.rb",
         | 
| 173 | 
            +
            		:line=>48,
         | 
| 174 | 
            +
            		:method=>:and_another_test_in_another_object},
         | 
| 175 | 
            +
            	 {:object=>#<Test:0x0000010081ba10>,
         | 
| 176 | 
            +
            		:file=>"sender_test.rb",
         | 
| 177 | 
            +
            		:line=>21,
         | 
| 178 | 
            +
            		:method=>:another_test},
         | 
| 179 | 
            +
            	 {:object=>#<Test:0x0000010081ba10>,
         | 
| 180 | 
            +
            		:file=>"sender_test.rb",
         | 
| 181 | 
            +
            		:line=>15,
         | 
| 182 | 
            +
            		:method=>:test},
         | 
| 183 | 
            +
            	 {:object=>main, :file=>"sender_test.rb", :line=>96, :method=>:"<main>"},
         | 
| 149 184 | 
             
            	 {:object=>main, :file=>"<main>", :line=>0, :method=>:"<main>"}]
         | 
| 150 | 
            -
            	[{:object=>#<Test2: | 
| 151 | 
            -
             | 
| 152 | 
            -
             | 
| 153 | 
            -
             | 
| 154 | 
            -
            	 {:object=>#<Test: | 
| 155 | 
            -
             | 
| 156 | 
            -
             | 
| 157 | 
            -
             | 
| 185 | 
            +
            	[{:object=>#<Test2:0x0000010081a7e8>,
         | 
| 186 | 
            +
            		:file=>"sender_test.rb",
         | 
| 187 | 
            +
            		:line=>49,
         | 
| 188 | 
            +
            		:method=>:and_another_test_in_another_object},
         | 
| 189 | 
            +
            	 {:object=>#<Test:0x0000010081ba10>,
         | 
| 190 | 
            +
            		:file=>"sender_test.rb",
         | 
| 191 | 
            +
            		:line=>21,
         | 
| 192 | 
            +
            		:method=>:another_test}]
         | 
| 158 193 | 
             
            	These should be true:
         | 
| 159 194 | 
             
            	true
         | 
| 160 195 | 
             
            	true
         | 
| 161 196 | 
             
            	true
         | 
| 162 197 | 
             
            	true
         | 
| 198 | 
            +
            	true
         | 
| 163 199 | 
             
            	These should be false:
         | 
| 164 200 | 
             
            	false
         | 
| 165 201 | 
             
            	false
         | 
| 166 202 | 
             
            	false
         | 
| 167 203 | 
             
            	false
         | 
| 204 | 
            +
            	false
         | 
| 205 | 
            +
            	And now we get a step by step backtrace
         | 
| 206 | 
            +
            	Frame number 1:
         | 
| 207 | 
            +
            	{:object=>#<Test:0x0000010081ba10>,
         | 
| 208 | 
            +
            	 :file=>"sender_test.rb",
         | 
| 209 | 
            +
            	 :line=>21,
         | 
| 210 | 
            +
            	 :method=>:another_test}
         | 
| 211 | 
            +
            	Frame number 2:
         | 
| 212 | 
            +
            	{:object=>#<Test:0x0000010081ba10>,
         | 
| 213 | 
            +
            	 :file=>"sender_test.rb",
         | 
| 214 | 
            +
            	 :line=>15,
         | 
| 215 | 
            +
            	 :method=>:test}
         | 
| 216 | 
            +
            	Frame number 3:
         | 
| 217 | 
            +
            	{:object=>main, :file=>"sender_test.rb", :line=>96, :method=>:"<main>"}
         | 
| 218 | 
            +
            	Frame number 4:
         | 
| 219 | 
            +
            	{:object=>main, :file=>"<main>", :line=>0, :method=>:"<main>"}
         | 
| 220 | 
            +
            	And now we try a backtrace inside a block.
         | 
| 221 | 
            +
            	[{:object=>#<Test2:0x0000010081a7e8>,
         | 
| 222 | 
            +
            		:file=>"sender_test.rb",
         | 
| 223 | 
            +
            		:line=>73,
         | 
| 224 | 
            +
            		:method=>:"block in and_another_test_in_another_object"},
         | 
| 225 | 
            +
            	 {:object=>["one_item"], :file=>nil, :line=>nil, :method=>:each},
         | 
| 226 | 
            +
            	 {:object=>#<Test2:0x0000010081a7e8>,
         | 
| 227 | 
            +
            		:file=>"sender_test.rb",
         | 
| 228 | 
            +
            		:line=>72,
         | 
| 229 | 
            +
            		:method=>:and_another_test_in_another_object},
         | 
| 230 | 
            +
            	 {:object=>#<Test:0x0000010081ba10>,
         | 
| 231 | 
            +
            		:file=>"sender_test.rb",
         | 
| 232 | 
            +
            		:line=>21,
         | 
| 233 | 
            +
            		:method=>:another_test},
         | 
| 234 | 
            +
            	 {:object=>#<Test:0x0000010081ba10>,
         | 
| 235 | 
            +
            		:file=>"sender_test.rb",
         | 
| 236 | 
            +
            		:line=>15,
         | 
| 237 | 
            +
            		:method=>:test},
         | 
| 238 | 
            +
            	 {:object=>main, :file=>"sender_test.rb", :line=>96, :method=>:"<main>"},
         | 
| 239 | 
            +
            	 {:object=>main, :file=>"<main>", :line=>0, :method=>:"<main>"}]
         | 
| 240 | 
            +
            	And :backtrace_includes_one_of?; this should be true:
         | 
| 241 | 
            +
            	true
         | 
| 242 | 
            +
            	as should this:
         | 
| 243 | 
            +
            	true
         | 
| 244 | 
            +
            	And :backtrace_frame_with; this should be a Hash:
         | 
| 245 | 
            +
            	{:object=>#<Test:0x0000010081ba10>,
         | 
| 246 | 
            +
            	 :file=>"sender_test.rb",
         | 
| 247 | 
            +
            	 :line=>15,
         | 
| 248 | 
            +
            	 :method=>:test}
         | 
| 249 | 
            +
            	as should this:
         | 
| 250 | 
            +
            	{:object=>#<Test:0x0000010081ba10>,
         | 
| 251 | 
            +
            	 :file=>"sender_test.rb",
         | 
| 252 | 
            +
            	 :line=>21,
         | 
| 253 | 
            +
            	 :method=>:another_test}
         | 
| 254 | 
            +
            	And :backtrace_frames_with; this should be an Array of Hashes
         | 
| 255 | 
            +
            	[{:object=>#<Test:0x0000010081ba10>,
         | 
| 256 | 
            +
            		:file=>"sender_test.rb",
         | 
| 257 | 
            +
            		:line=>21,
         | 
| 258 | 
            +
            		:method=>:another_test},
         | 
| 259 | 
            +
            	 {:object=>#<Test:0x0000010081ba10>,
         | 
| 260 | 
            +
            		:file=>"sender_test.rb",
         | 
| 261 | 
            +
            		:line=>15,
         | 
| 262 | 
            +
            		:method=>:test}]
         | 
| 263 | 
            +
            	as should this:
         | 
| 264 | 
            +
            	[{:object=>#<Test:0x0000010081ba10>,
         | 
| 265 | 
            +
            		:file=>"sender_test.rb",
         | 
| 266 | 
            +
            		:line=>21,
         | 
| 267 | 
            +
            		:method=>:another_test},
         | 
| 268 | 
            +
            	 {:object=>#<Test:0x0000010081ba10>,
         | 
| 269 | 
            +
            		:file=>"sender_test.rb",
         | 
| 270 | 
            +
            		:line=>15,
         | 
| 271 | 
            +
            		:method=>:test},
         | 
| 272 | 
            +
            	 {:object=>main, :file=>"sender_test.rb", :line=>96, :method=>:"<main>"}]
         | 
| 273 | 
            +
            	And try iterating with an Enumerator
         | 
| 274 | 
            +
            	#<Enumerator:0x000001010480e0>
         | 
| 275 | 
            +
            	{:object=>#<Test2:0x0000010081a388>,
         | 
| 276 | 
            +
            	 :file=>"sender_test.rb",
         | 
| 277 | 
            +
            	 :line=>92,
         | 
| 278 | 
            +
            	 :method=>:and_another_test_in_another_object}
         | 
| 279 | 
            +
            	{:object=>#<Test:0x0000010081b770>,
         | 
| 280 | 
            +
            	 :file=>"sender_test.rb",
         | 
| 281 | 
            +
            	 :line=>21,
         | 
| 282 | 
            +
            	 :method=>:another_test}
         | 
| 283 | 
            +
            	{:object=>#<Test:0x0000010081b770>,
         | 
| 284 | 
            +
            	 :file=>"sender_test.rb",
         | 
| 285 | 
            +
            	 :line=>15,
         | 
| 286 | 
            +
            	 :method=>:test}
         | 
| 287 | 
            +
            	{:object=>main, :file=>"sender_test.rb", :line=>103, :method=>:"<main>"}
         | 
| 288 | 
            +
            	{:object=>main, :file=>"<main>", :line=>0, :method=>:"<main>"}
         | 
| 289 | 
            +
            	sender_test.rb:94:in `next': iteration reached at end (StopIteration)
         | 
| 290 | 
            +
            		from sender_test.rb:94:in `and_another_test_in_another_object'
         | 
| 291 | 
            +
            		from sender_test.rb:21:in `another_test'
         | 
| 292 | 
            +
            		from sender_test.rb:15:in `test'
         | 
| 293 | 
            +
            		from sender_test.rb:103:in `<main>'
         | 
| 168 294 | 
             
            	Finished Test.
         | 
| 169 295 |  | 
| 170 296 | 
             
            == LICENSE:
         | 
    
        data/Rakefile
    CHANGED
    
    | @@ -5,13 +5,13 @@ require 'rake/extensiontask' | |
| 5 5 | 
             
            Hoe.spec 'sender' do
         | 
| 6 6 | 
             
              developer( 'Asher', 'asher@ridiculouspower.com' )
         | 
| 7 7 | 
             
              self.rubyforge_name   = 'asher'
         | 
| 8 | 
            +
              self.version          = File.open( 'VERSION.rdoc' ).readline
         | 
| 8 9 | 
             
              self.readme_file			= 'README.rdoc'
         | 
| 9 10 | 
             
              self.history_file     = 'CHANGELOG.rdoc'
         | 
| 10 11 | 
             
              self.extra_rdoc_files	= FileList['*.rdoc']
         | 
| 11 12 | 
             
              self.spec_extras			= { :extensions => ["ext/sender/extconf.rb"] }
         | 
| 12 13 | 
             
              self.extra_dev_deps << ['rake-compiler', '>= 0']  
         | 
| 13 14 |  | 
| 14 | 
            -
              self.version=File.open( 'VERSION.rdoc' ).readline
         | 
| 15 15 |  | 
| 16 16 | 
             
              Rake::ExtensionTask.new( 'sender', spec ) do |ext|
         | 
| 17 17 | 
             
                ext.lib_dir = File.join('lib', 'sender')
         | 
    
        data/VERSION.rdoc
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            1. | 
| 1 | 
            +
            1.5
         | 
| @@ -4,6 +4,11 @@ | |
| 4 4 | 
             
            	#include "ruby.h"
         | 
| 5 5 | 
             
            	#include "eval_intern.h"
         | 
| 6 6 |  | 
| 7 | 
            +
            	typedef enum BOOL_e	{
         | 
| 8 | 
            +
            		FALSE,
         | 
| 9 | 
            +
            		TRUE
         | 
| 10 | 
            +
            	} BOOL;
         | 
| 11 | 
            +
             | 
| 7 12 | 
             
            	rb_control_frame_t* RPRuby_internal_framePriorTo( rb_control_frame_t* control_frame );
         | 
| 8 13 | 
             
            	VALUE RPSender_internal_backtraceHashForControlFrame( const rb_control_frame_t* c_top_of_control_frame );
         | 
| 9 14 |  | 
| @@ -65,11 +65,16 @@ found: | |
| 65 65 | 
             
                return line_no;
         | 
| 66 66 | 
             
            }
         | 
| 67 67 |  | 
| 68 | 
            -
             | 
| 69 | 
            -
             | 
| 70 | 
            -
             | 
| 71 | 
            -
             | 
| 72 | 
            -
             | 
| 73 | 
            -
             | 
| 74 | 
            -
             | 
| 75 | 
            -
             | 
| 68 | 
            +
            struct enumerator* enumerator_ptr(VALUE obj)
         | 
| 69 | 
            +
            {
         | 
| 70 | 
            +
                struct enumerator *ptr;
         | 
| 71 | 
            +
            	
         | 
| 72 | 
            +
                Data_Get_Struct(obj, struct enumerator, ptr);
         | 
| 73 | 
            +
            	
         | 
| 74 | 
            +
            	//	modified because a call to a local version of enumerator_mark won't verify
         | 
| 75 | 
            +
            	
         | 
| 76 | 
            +
                if (!ptr || ptr->obj == Qundef) {
         | 
| 77 | 
            +
            		rb_raise(rb_eArgError, "uninitialized enumerator");
         | 
| 78 | 
            +
                }
         | 
| 79 | 
            +
                return ptr;
         | 
| 80 | 
            +
            }
         | 
| @@ -5,8 +5,69 @@ | |
| 5 5 | 
             
            	#include "eval_intern.h"
         | 
| 6 6 | 
             
            	#include "vm_core.h"
         | 
| 7 7 |  | 
| 8 | 
            +
            	#define MAX_POSBUF 128
         | 
| 9 | 
            +
             | 
| 10 | 
            +
            	enum context_type {
         | 
| 11 | 
            +
            		CONTINUATION_CONTEXT = 0,
         | 
| 12 | 
            +
            		FIBER_CONTEXT = 1,
         | 
| 13 | 
            +
            		ROOT_FIBER_CONTEXT = 2
         | 
| 14 | 
            +
            	};
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            	typedef struct rb_context_struct {
         | 
| 17 | 
            +
            		enum context_type type;
         | 
| 18 | 
            +
            		VALUE self;
         | 
| 19 | 
            +
            		int argc;
         | 
| 20 | 
            +
            		VALUE value;
         | 
| 21 | 
            +
            		VALUE *vm_stack;
         | 
| 22 | 
            +
            	#ifdef CAPTURE_JUST_VALID_VM_STACK
         | 
| 23 | 
            +
            		int vm_stack_slen;  /* length of stack (head of th->stack) */
         | 
| 24 | 
            +
            		int vm_stack_clen;  /* length of control frames (tail of th->stack) */
         | 
| 25 | 
            +
            	#endif
         | 
| 26 | 
            +
            		VALUE *machine_stack;
         | 
| 27 | 
            +
            		VALUE *machine_stack_src;
         | 
| 28 | 
            +
            	#ifdef __ia64
         | 
| 29 | 
            +
            		VALUE *machine_register_stack;
         | 
| 30 | 
            +
            		VALUE *machine_register_stack_src;
         | 
| 31 | 
            +
            		int machine_register_stack_size;
         | 
| 32 | 
            +
            	#endif
         | 
| 33 | 
            +
            		rb_thread_t saved_thread;
         | 
| 34 | 
            +
            		rb_jmpbuf_t jmpbuf;
         | 
| 35 | 
            +
            		int machine_stack_size;
         | 
| 36 | 
            +
            	} rb_context_t;
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            	enum fiber_status {
         | 
| 39 | 
            +
            		CREATED,
         | 
| 40 | 
            +
            		RUNNING,
         | 
| 41 | 
            +
            		TERMINATED
         | 
| 42 | 
            +
            	};
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            	typedef struct rb_fiber_struct {
         | 
| 45 | 
            +
            		rb_context_t cont;
         | 
| 46 | 
            +
            		VALUE prev;
         | 
| 47 | 
            +
            		enum fiber_status status;
         | 
| 48 | 
            +
            		struct rb_fiber_struct *prev_fiber;
         | 
| 49 | 
            +
            		struct rb_fiber_struct *next_fiber;
         | 
| 50 | 
            +
            	} rb_fiber_t;
         | 
| 51 | 
            +
             | 
| 52 | 
            +
            	struct enumerator {
         | 
| 53 | 
            +
            		VALUE obj;
         | 
| 54 | 
            +
            		ID    meth;
         | 
| 55 | 
            +
            		VALUE args;
         | 
| 56 | 
            +
            		VALUE fib;
         | 
| 57 | 
            +
            		VALUE dst;
         | 
| 58 | 
            +
            		VALUE no_next;
         | 
| 59 | 
            +
            	};
         | 
| 60 | 
            +
             | 
| 61 | 
            +
            	#define GetFiberPtr(obj, ptr)  do {\
         | 
| 62 | 
            +
            				ptr = (rb_fiber_t*)DATA_PTR(obj);\
         | 
| 63 | 
            +
            				if (!ptr) rb_raise(rb_eFiberError, "uninitialized fiber");\
         | 
| 64 | 
            +
            			} while(0)
         | 
| 65 | 
            +
             | 
| 66 | 
            +
             | 
| 8 67 | 
             
            	ID frame_func_id( rb_control_frame_t *cfp );
         | 
| 9 68 | 
             
            	ID rb_frame_caller(void);
         | 
| 10 69 | 
             
            	int rb_vm_get_sourceline(const rb_control_frame_t *cfp);
         | 
| 11 | 
            -
             | 
| 70 | 
            +
            	void control_frame_dump(rb_thread_t *th, rb_control_frame_t *cfp);
         | 
| 71 | 
            +
            	struct enumerator* enumerator_ptr(VALUE obj);
         | 
| 72 | 
            +
            	
         | 
| 12 73 | 
             
            #endif
         | 
    
        data/ext/sender/rb_Kernel.c
    CHANGED
    
    | @@ -12,20 +12,29 @@ | |
| 12 12 |  | 
| 13 13 | 
             
            void Init_senderKernel()	{
         | 
| 14 14 |  | 
| 15 | 
            -
            	rb_define_singleton_method( rb_mKernel, "backtrace", | 
| 16 | 
            -
            	rb_define_singleton_method( rb_mKernel, " | 
| 15 | 
            +
            	rb_define_singleton_method( rb_mKernel, "backtrace",						rb_RPRuby_Sender_Kernel_backtrace,						-1 );
         | 
| 16 | 
            +
            	rb_define_singleton_method( rb_mKernel, "each_backtrace_frame",				rb_RPRuby_Sender_Kernel_each_backtrace_frame,			-1 );
         | 
| 17 | 
            +
            	rb_define_singleton_method( rb_mKernel, "backtrace_includes?",				rb_RPRuby_Sender_Kernel_backtrace_includes,				-1 );
         | 
| 18 | 
            +
            	rb_define_singleton_method( rb_mKernel, "backtrace_includes_one_of?",		rb_RPRuby_Sender_Kernel_backtrace_includes_one_of,		-1 );
         | 
| 19 | 
            +
            	rb_define_singleton_method( rb_mKernel, "backtrace_frame_with",				rb_RPRuby_Sender_Kernel_backtrace_frame_with,			-1 );
         | 
| 20 | 
            +
            	rb_define_singleton_method( rb_mKernel, "backtrace_frames_with",			rb_RPRuby_Sender_Kernel_backtrace_frames_with,			-1 );
         | 
| 21 | 
            +
             | 
| 17 22 |  | 
| 18 23 | 
             
            }
         | 
| 19 24 |  | 
| 25 | 
            +
            static VALUE rb_eFiberError;
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            #define RPRUBY_SENDER_ERROR_NO_ENUMERATORS							"Enumerators not currently enabled due to difficulty with Fiber support."
         | 
| 28 | 
            +
             | 
| 20 29 | 
             
            /***************************************************************************************************************************************************************
         | 
| 21 30 | 
             
            ****************************************************************************************************************************************************************
         | 
| 22 31 | 
             
            													Ruby Kernel Methods
         | 
| 23 32 | 
             
            ****************************************************************************************************************************************************************
         | 
| 24 33 | 
             
            ***************************************************************************************************************************************************************/
         | 
| 25 34 |  | 
| 26 | 
            -
             | 
| 27 | 
            -
             *   | 
| 28 | 
            -
              | 
| 35 | 
            +
            /**********************
         | 
| 36 | 
            +
             *  Kernel.backtrace  *
         | 
| 37 | 
            +
             *********************/
         | 
| 29 38 |  | 
| 30 39 | 
             
            /*
         | 
| 31 40 | 
             
             * call-seq:
         | 
| @@ -73,6 +82,10 @@ VALUE rb_RPRuby_Sender_Kernel_backtrace(	int		argc, | |
| 73 82 |  | 
| 74 83 | 
             
            		VALUE	rb_frame_hash	=	rb_RPRuby_Sender_Kernel_internal_backtraceHashForControlFrame(	& c_current_context_frame );
         | 
| 75 84 |  | 
| 85 | 
            +
            		if ( rb_frame_hash == Qnil )	{
         | 
| 86 | 
            +
            			break;
         | 
| 87 | 
            +
            		}
         | 
| 88 | 
            +
            		
         | 
| 76 89 | 
             
            		//	push hash to array
         | 
| 77 90 | 
             
            		rb_ary_push(	rb_return_array,
         | 
| 78 91 | 
             
            						rb_frame_hash );
         | 
| @@ -84,10 +97,83 @@ VALUE rb_RPRuby_Sender_Kernel_backtrace(	int		argc, | |
| 84 97 | 
             
               return rb_return_array;
         | 
| 85 98 | 
             
            }
         | 
| 86 99 |  | 
| 100 | 
            +
            /*********************************
         | 
| 101 | 
            +
             *  Kernel.each_backtrace_frame  *
         | 
| 102 | 
            +
             ********************************/
         | 
| 103 | 
            +
             | 
| 104 | 
            +
            /*
         | 
| 105 | 
            +
             * call-seq:
         | 
| 106 | 
            +
             *   Kernel.each_backtrace_frame( & block )
         | 
| 107 | 
            +
             *
         | 
| 108 | 
            +
             * Return array of hashes with object and method frame information for backtrace.
         | 
| 109 | 
            +
             * Specifying number_of_frames will cause only the last number_of_frames to be returned.
         | 
| 110 | 
            +
             * Kernel.backtrace returns all frames including the current context (__method__/__callee__).
         | 
| 111 | 
            +
             */
         | 
| 112 | 
            +
            VALUE rb_RPRuby_Sender_Kernel_each_backtrace_frame(	int		argc,
         | 
| 113 | 
            +
            													VALUE*	args,
         | 
| 114 | 
            +
            													VALUE	rb_self )	{
         | 
| 115 | 
            +
             | 
| 116 | 
            +
            	rb_thread_t*			c_thread					= GET_THREAD();
         | 
| 117 | 
            +
            	//	Get the current frame - we're doing a backtrace, so our current working frame to start is the first previous thread
         | 
| 118 | 
            +
            	rb_control_frame_t*		c_current_context_frame		= RUBY_VM_PREVIOUS_CONTROL_FRAME( RUBY_VM_PREVIOUS_CONTROL_FRAME( c_thread->cfp ) );
         | 
| 119 | 
            +
            	
         | 
| 120 | 
            +
            	//	c_top_of_control_frame describes the top edge of the stack trace
         | 
| 121 | 
            +
            	//	set c_top_of_control_frame to the first frame in <main>
         | 
| 122 | 
            +
                rb_control_frame_t*		c_top_of_control_frame	=	RUBY_VM_NEXT_CONTROL_FRAME( RUBY_VM_NEXT_CONTROL_FRAME( (void *)( c_thread->stack + c_thread->stack_size ) ) );
         | 
| 123 | 
            +
            	
         | 
| 124 | 
            +
            	VALUE	rb_stored_backtrace_array	=	Qnil;
         | 
| 125 | 
            +
            	
         | 
| 126 | 
            +
            	//	if we were passed a stored backtrace array, use it
         | 
| 127 | 
            +
            	if (	argc == 1
         | 
| 128 | 
            +
            		&&	TYPE( args[ 0 ] ) == T_ARRAY )	{
         | 
| 129 | 
            +
            		rb_stored_backtrace_array	=	args[ 0 ];
         | 
| 130 | 
            +
            	}
         | 
| 131 | 
            +
            				
         | 
| 132 | 
            +
            	//	for each control frame:
         | 
| 133 | 
            +
                while ( c_current_context_frame < c_top_of_control_frame ) {
         | 
| 134 | 
            +
             | 
| 135 | 
            +
            		VALUE	rb_frame_hash;
         | 
| 136 | 
            +
            		//	if we are using a stored backtrace we don't need to ask for a new hash
         | 
| 137 | 
            +
            		if ( rb_stored_backtrace_array == Qnil )	{
         | 
| 138 | 
            +
            			rb_frame_hash	=	rb_RPRuby_Sender_Kernel_internal_backtraceHashForControlFrame(	& c_current_context_frame );
         | 
| 139 | 
            +
            		}
         | 
| 140 | 
            +
            		else {
         | 
| 141 | 
            +
            			rb_frame_hash	=	rb_ary_shift( rb_stored_backtrace_array );
         | 
| 142 | 
            +
            		}
         | 
| 87 143 |  | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 90 | 
            -
             | 
| 144 | 
            +
            		if ( rb_frame_hash == Qnil )	{
         | 
| 145 | 
            +
            			break;
         | 
| 146 | 
            +
            		}
         | 
| 147 | 
            +
            		
         | 
| 148 | 
            +
            		//	if we try to iterate using an Enumerator we will lose our context
         | 
| 149 | 
            +
            		if ( ! rb_block_given_p() )	{
         | 
| 150 | 
            +
            			
         | 
| 151 | 
            +
            			//	we solve this by assuming that the desired context is the moment when each_backtrace_frame is called
         | 
| 152 | 
            +
            			//	this allows us to store the backtrace and iterate it as we want
         | 
| 153 | 
            +
            			//	the only downside is that we have to get the entire backtrace first in order to store it
         | 
| 154 | 
            +
            			rb_stored_backtrace_array	=	rb_RPRuby_Sender_Kernel_backtrace(	0,
         | 
| 155 | 
            +
            																				NULL,
         | 
| 156 | 
            +
            																				rb_self );
         | 
| 157 | 
            +
            		
         | 
| 158 | 
            +
            			RETURN_ENUMERATOR( rb_self, 1, & rb_stored_backtrace_array );
         | 
| 159 | 
            +
            			//rb_raise( rb_eArgError, RPRUBY_SENDER_ERROR_NO_ENUMERATORS );
         | 
| 160 | 
            +
            		}
         | 
| 161 | 
            +
            		
         | 
| 162 | 
            +
            		//	otherwise, yield the block
         | 
| 163 | 
            +
            		rb_yield( rb_frame_hash );
         | 
| 164 | 
            +
            		
         | 
| 165 | 
            +
            		//	only move the frame if we are not using a stored backtrace
         | 
| 166 | 
            +
            		if ( rb_stored_backtrace_array == Qnil )	{
         | 
| 167 | 
            +
            			c_current_context_frame = RUBY_VM_PREVIOUS_CONTROL_FRAME( c_current_context_frame );		
         | 
| 168 | 
            +
            		}
         | 
| 169 | 
            +
            	}
         | 
| 170 | 
            +
            	
         | 
| 171 | 
            +
            	return Qnil;
         | 
| 172 | 
            +
            }
         | 
| 173 | 
            +
            	
         | 
| 174 | 
            +
            /********************************
         | 
| 175 | 
            +
             *  Kernel.backtrace_includes?  *
         | 
| 176 | 
            +
             *******************************/
         | 
| 91 177 |  | 
| 92 178 | 
             
            /*
         | 
| 93 179 | 
             
             * call-seq:
         | 
| @@ -102,12 +188,40 @@ VALUE rb_RPRuby_Sender_Kernel_backtrace_includes(	int		argc, | |
| 102 188 | 
             
            													VALUE*	args,
         | 
| 103 189 | 
             
            													VALUE	rb_self )	{
         | 
| 104 190 |  | 
| 191 | 
            +
            	//	this function is also used for 
         | 
| 192 | 
            +
            	//	* backtrace_includes_one_of?
         | 
| 193 | 
            +
            	//	* backtrace_includes_frame?
         | 
| 194 | 
            +
            	//	* backtrace_includes_one_of_frames?
         | 
| 195 | 
            +
            	
         | 
| 105 196 | 
             
            	//	create tracking array
         | 
| 106 197 | 
             
            	VALUE	rb_tracking_array	=	rb_ary_new();
         | 
| 107 198 |  | 
| 108 199 | 
             
            	//	populate tracking array with methods/objects
         | 
| 109 | 
            -
            	 | 
| 110 | 
            -
            	 | 
| 200 | 
            +
            	//	optional - if first arg is Qtrue, we are looking for one of the args instead of all of the args
         | 
| 201 | 
            +
            	int		c_which_arg				=	0;
         | 
| 202 | 
            +
            	BOOL	c_requires_all_items	= TRUE;
         | 
| 203 | 
            +
            	if (	args[ 0 ] == Qnil
         | 
| 204 | 
            +
            		||	(	argc > 1
         | 
| 205 | 
            +
            			 &&	args[ 1 ] == Qnil ) )	{
         | 
| 206 | 
            +
            		c_which_arg++;
         | 
| 207 | 
            +
            		c_requires_all_items = FALSE;
         | 
| 208 | 
            +
            	}
         | 
| 209 | 
            +
            	BOOL	c_return_frame	=	FALSE;
         | 
| 210 | 
            +
            	if (	args[ 0 ] == Qfalse
         | 
| 211 | 
            +
            		||	(	argc > 1
         | 
| 212 | 
            +
            			 &&	args[ 1 ] == Qfalse ) )	{
         | 
| 213 | 
            +
            		c_which_arg++;
         | 
| 214 | 
            +
            		c_return_frame = TRUE;
         | 
| 215 | 
            +
            	}
         | 
| 216 | 
            +
            	BOOL	c_return_all_frames	=	FALSE;
         | 
| 217 | 
            +
            	if (	args[ 0 ] == Qtrue
         | 
| 218 | 
            +
            		||	(	argc > 1
         | 
| 219 | 
            +
            			 &&	args[ 1 ] == Qtrue ) )	{
         | 
| 220 | 
            +
            		c_which_arg++;
         | 
| 221 | 
            +
            		c_return_all_frames = TRUE;
         | 
| 222 | 
            +
            	}
         | 
| 223 | 
            +
            	int	c_args_offset	=	c_which_arg;
         | 
| 224 | 
            +
            	for ( ; c_which_arg < argc ; c_which_arg++ )	{
         | 
| 111 225 | 
             
            		rb_ary_push(	rb_tracking_array,
         | 
| 112 226 | 
             
            						args[ c_which_arg ] );
         | 
| 113 227 | 
             
            	}
         | 
| @@ -120,6 +234,29 @@ VALUE rb_RPRuby_Sender_Kernel_backtrace_includes(	int		argc, | |
| 120 234 | 
             
            	//	set c_top_of_control_frame to the first frame in <main>
         | 
| 121 235 | 
             
                rb_control_frame_t*		c_top_of_control_frame	=	RUBY_VM_NEXT_CONTROL_FRAME( RUBY_VM_NEXT_CONTROL_FRAME( (void *)( c_thread->stack + c_thread->stack_size ) ) );
         | 
| 122 236 |  | 
| 237 | 
            +
            	VALUE	rb_test_index_array	=	rb_ary_new();
         | 
| 238 | 
            +
            	//	:object
         | 
| 239 | 
            +
            	//	instance or class
         | 
| 240 | 
            +
            	rb_ary_push(	rb_test_index_array,
         | 
| 241 | 
            +
            					ID2SYM( rb_intern( "object" ) ) );
         | 
| 242 | 
            +
            	//	:method				
         | 
| 243 | 
            +
            	rb_ary_push(	rb_test_index_array,
         | 
| 244 | 
            +
            					ID2SYM( rb_intern( "method" ) ) );
         | 
| 245 | 
            +
            	//	:file
         | 
| 246 | 
            +
            	rb_ary_push(	rb_test_index_array,
         | 
| 247 | 
            +
            					ID2SYM( rb_intern( "file" ) ) );
         | 
| 248 | 
            +
            	//	:line
         | 
| 249 | 
            +
            	rb_ary_push(	rb_test_index_array,
         | 
| 250 | 
            +
            					ID2SYM( rb_intern( "line" ) ) );
         | 
| 251 | 
            +
            	
         | 
| 252 | 
            +
            	//	only used if c_return_all_frames == TRUE
         | 
| 253 | 
            +
            	VALUE	rb_frame_hashes_array	=	Qnil;
         | 
| 254 | 
            +
            	if ( c_return_all_frames == TRUE )	{
         | 
| 255 | 
            +
            		rb_frame_hashes_array		=	rb_ary_new();
         | 
| 256 | 
            +
            	}
         | 
| 257 | 
            +
            	
         | 
| 258 | 
            +
            	VALUE	rb_frame_hash;
         | 
| 259 | 
            +
            	
         | 
| 123 260 | 
             
            	//	for each control frame:
         | 
| 124 261 | 
             
                while ( c_current_context_frame < c_top_of_control_frame ) {
         | 
| 125 262 |  | 
| @@ -127,61 +264,272 @@ VALUE rb_RPRuby_Sender_Kernel_backtrace_includes(	int		argc, | |
| 127 264 | 
             
            		int	c_which_member;
         | 
| 128 265 | 
             
            		for ( c_which_member = 0 ; c_which_member < RARRAY_LEN( rb_tracking_array ) ; c_which_member++ )	{
         | 
| 129 266 |  | 
| 130 | 
            -
            			VALUE	 | 
| 267 | 
            +
            			VALUE	rb_this_arg	=	args[ c_which_member + c_args_offset ];
         | 
| 131 268 |  | 
| 132 | 
            -
            			 | 
| 269 | 
            +
            			BOOL		matched	=	FALSE;
         | 
| 133 270 |  | 
| 134 | 
            -
            			 | 
| 135 | 
            -
            			 | 
| 136 | 
            -
             | 
| 137 | 
            -
             | 
| 138 | 
            -
             | 
| 271 | 
            +
            			rb_frame_hash	=	rb_RPRuby_Sender_Kernel_internal_backtraceHashForControlFrame(	& c_current_context_frame );
         | 
| 272 | 
            +
            			
         | 
| 273 | 
            +
            			//	if we have a hash we are testing multiple items in a frame
         | 
| 274 | 
            +
            			if ( TYPE( rb_this_arg ) == T_HASH )	{
         | 
| 275 | 
            +
             | 
| 276 | 
            +
            				VALUE	rb_frame_test_array	=	rb_obj_clone( rb_test_index_array );
         | 
| 277 | 
            +
            			
         | 
| 278 | 
            +
            				//	for each element that we could test for
         | 
| 279 | 
            +
            				int	c_which_index;
         | 
| 280 | 
            +
            				int	c_skipped_index_count	=	0;
         | 
| 281 | 
            +
            				for ( c_which_index = 0 ; c_which_index < RARRAY_LEN( rb_frame_test_array ) ; c_which_index++ )	{
         | 
| 282 | 
            +
            					
         | 
| 283 | 
            +
            					VALUE	rb_this_index	=	RARRAY_PTR( rb_frame_test_array )[ c_which_index ];
         | 
| 284 | 
            +
            					
         | 
| 285 | 
            +
            					//	see if our requested test hash includes the potential test element
         | 
| 286 | 
            +
            					if ( rb_hash_lookup(	rb_this_arg,
         | 
| 287 | 
            +
            											rb_this_index ) != Qnil )	{
         | 
| 288 | 
            +
            						
         | 
| 289 | 
            +
            						VALUE	rb_required_element	=	rb_hash_aref(	rb_this_arg,
         | 
| 290 | 
            +
            																		rb_this_index );
         | 
| 291 | 
            +
            						VALUE	rb_frame_element	=	rb_hash_aref(	rb_frame_hash,
         | 
| 292 | 
            +
            																		rb_this_index	);
         | 
| 293 | 
            +
            									 						
         | 
| 294 | 
            +
            						//	if it does, we need to see if the current frame's element matches this element
         | 
| 295 | 
            +
            						VALUE	rb_required_element_klass;
         | 
| 296 | 
            +
            						if ( rb_required_element == rb_frame_element
         | 
| 297 | 
            +
            							//	if we have a string, which is a filename
         | 
| 298 | 
            +
            							||	(	TYPE( rb_required_element ) == T_STRING
         | 
| 299 | 
            +
            								 &&	rb_funcall( rb_frame_element, rb_intern( "==" ), 1, rb_required_element ) == Qtrue )
         | 
| 300 | 
            +
            							//	if we have a class, which is a special case for :object
         | 
| 301 | 
            +
            							||	(	rb_this_index == ID2SYM( rb_intern( "class" ) ) 
         | 
| 302 | 
            +
            								 &&	( rb_required_element_klass = ( ( TYPE( rb_required_element ) == T_CLASS ) ? rb_required_element : rb_funcall( rb_required_element, rb_intern( "class" ), 0 ) ) )
         | 
| 303 | 
            +
            								 &&	rb_required_element_klass == rb_required_element ) )	{
         | 
| 304 | 
            +
             | 
| 305 | 
            +
            							rb_ary_delete_at(	rb_frame_test_array,
         | 
| 306 | 
            +
            												c_which_index );
         | 
| 307 | 
            +
            							c_which_index--;
         | 
| 308 | 
            +
            						}
         | 
| 309 | 
            +
            					}
         | 
| 310 | 
            +
            					else {
         | 
| 311 | 
            +
            						c_skipped_index_count++;
         | 
| 312 | 
            +
            					}
         | 
| 313 | 
            +
             | 
| 314 | 
            +
            					if ( RARRAY_LEN( rb_frame_test_array ) == c_skipped_index_count )	{
         | 
| 315 | 
            +
            						if ( c_return_frame == TRUE )	{
         | 
| 316 | 
            +
            							return rb_frame_hash;
         | 
| 317 | 
            +
            						}
         | 
| 318 | 
            +
            						else if ( c_return_all_frames == TRUE )	{
         | 
| 319 | 
            +
            							rb_ary_push(	rb_frame_hashes_array,
         | 
| 320 | 
            +
            											rb_frame_hash );
         | 
| 321 | 
            +
            						}
         | 
| 322 | 
            +
            						else {
         | 
| 323 | 
            +
            							return Qtrue;							
         | 
| 324 | 
            +
            						}
         | 
| 325 | 
            +
            					}					
         | 
| 139 326 | 
             
            				}
         | 
| 140 327 | 
             
            			}
         | 
| 141 | 
            -
            			 | 
| 142 | 
            -
             | 
| 143 | 
            -
             | 
| 144 | 
            -
            				if | 
| 145 | 
            -
             | 
| 328 | 
            +
            			else {
         | 
| 329 | 
            +
             | 
| 330 | 
            +
            				//	:object => <class:instance>
         | 
| 331 | 
            +
            				if	(	TYPE( rb_this_arg ) == T_OBJECT )	{
         | 
| 332 | 
            +
             | 
| 333 | 
            +
            					if ( rb_hash_aref(	rb_frame_hash,
         | 
| 334 | 
            +
            										ID2SYM( rb_intern( "object" ) ) ) == rb_this_arg )	{
         | 
| 335 | 
            +
            						matched = TRUE;
         | 
| 336 | 
            +
            					}
         | 
| 146 337 | 
             
            				}
         | 
| 147 | 
            -
             | 
| 148 | 
            -
             | 
| 149 | 
            -
             | 
| 150 | 
            -
             | 
| 151 | 
            -
             | 
| 152 | 
            -
            					 | 
| 338 | 
            +
            				//	:object => <class>
         | 
| 339 | 
            +
            				else if	( TYPE( rb_this_arg ) == T_CLASS )	{
         | 
| 340 | 
            +
            					
         | 
| 341 | 
            +
            					VALUE	rb_frame_object			=	rb_hash_aref(	rb_frame_hash,
         | 
| 342 | 
            +
            																		ID2SYM( rb_intern( "object" ) ) );
         | 
| 343 | 
            +
            					VALUE	rb_frame_object_klass	=	TYPE( rb_frame_object ) == T_CLASS ? rb_frame_object : rb_funcall( rb_frame_object, rb_intern( "class" ), 0 );
         | 
| 344 | 
            +
            					if ( rb_frame_object_klass == rb_this_arg )	{
         | 
| 345 | 
            +
            						matched = TRUE;
         | 
| 346 | 
            +
            					}
         | 
| 347 | 
            +
            				}
         | 
| 348 | 
            +
            				//	:method => :method
         | 
| 349 | 
            +
            				else if	( TYPE( rb_this_arg ) == T_SYMBOL )	{
         | 
| 350 | 
            +
            				   
         | 
| 351 | 
            +
            					if ( rb_hash_aref(	rb_frame_hash,
         | 
| 352 | 
            +
            										ID2SYM( rb_intern( "method" ) ) ) == rb_this_arg )	{
         | 
| 353 | 
            +
            						matched = TRUE;
         | 
| 354 | 
            +
            					}
         | 
| 355 | 
            +
            				}
         | 
| 356 | 
            +
            				//	:file => "filename"
         | 
| 357 | 
            +
            				else if ( TYPE( rb_this_arg ) == T_STRING )	{
         | 
| 358 | 
            +
            					VALUE	rb_filename	=	rb_hash_aref(	rb_frame_hash,
         | 
| 359 | 
            +
            															ID2SYM( rb_intern( "file" ) ) );
         | 
| 360 | 
            +
            					VALUE	rb_comparison	=	rb_funcall( rb_filename, rb_intern( "==" ), 1, rb_this_arg );
         | 
| 361 | 
            +
            					if ( rb_comparison == Qtrue )	{
         | 
| 362 | 
            +
            						matched = TRUE;
         | 
| 363 | 
            +
            					}
         | 
| 364 | 
            +
            				}
         | 
| 365 | 
            +
            				//	:line => number
         | 
| 366 | 
            +
            				else if ( TYPE( rb_this_arg ) == T_FIXNUM )	{
         | 
| 367 | 
            +
            					if ( rb_hash_aref(	rb_frame_hash,
         | 
| 368 | 
            +
            										ID2SYM( rb_intern( "line" ) ) ) == rb_this_arg )	{
         | 
| 369 | 
            +
            						matched = TRUE;
         | 
| 370 | 
            +
            					}
         | 
| 153 371 | 
             
            				}
         | 
| 154 | 
            -
            			}
         | 
| 155 | 
            -
            		   
         | 
| 156 | 
            -
            			//	if array member exists in frame, remove from array
         | 
| 157 | 
            -
            			if ( matched )	{
         | 
| 158 | 
            -
            				//	delete this index
         | 
| 159 | 
            -
            				rb_ary_delete_at(	rb_tracking_array,
         | 
| 160 | 
            -
            									c_which_member );
         | 
| 161 372 |  | 
| 162 | 
            -
            				//	 | 
| 163 | 
            -
            				 | 
| 164 | 
            -
             | 
| 373 | 
            +
            				//	if array member exists in frame, remove from array
         | 
| 374 | 
            +
            				if ( matched )	{
         | 
| 375 | 
            +
            					if ( c_requires_all_items == FALSE )	{
         | 
| 376 | 
            +
            						if ( c_return_frame == TRUE )	{
         | 
| 377 | 
            +
            							return rb_frame_hash;
         | 
| 378 | 
            +
            						}
         | 
| 379 | 
            +
            						else {
         | 
| 380 | 
            +
            							return Qtrue;							
         | 
| 381 | 
            +
            						}
         | 
| 382 | 
            +
             | 
| 383 | 
            +
            					}
         | 
| 384 | 
            +
            					else {
         | 
| 385 | 
            +
            						
         | 
| 386 | 
            +
            						//	delete this index
         | 
| 387 | 
            +
            						rb_ary_delete_at(	rb_tracking_array,
         | 
| 388 | 
            +
            											c_which_member );
         | 
| 389 | 
            +
            						
         | 
| 390 | 
            +
            						//	decrement the loop iterator so that the increase is offset
         | 
| 391 | 
            +
            						//	this is necessary since we just removed an index and are iterating vs. the length of the array
         | 
| 392 | 
            +
            						c_which_member--;
         | 
| 393 | 
            +
            					}
         | 
| 394 | 
            +
            				}
         | 
| 165 395 | 
             
            			}
         | 
| 166 396 | 
             
            		}
         | 
| 167 397 |  | 
| 168 398 | 
             
            		//	if array is empty, return true
         | 
| 169 399 | 
             
            		//	we check here as well as at the end so we can stop iterating the backtrace if we find all our items
         | 
| 170 400 | 
             
            		if ( RARRAY_LEN( rb_tracking_array ) == 0 )	{
         | 
| 171 | 
            -
            			 | 
| 401 | 
            +
            			if ( c_return_frame == TRUE )	{
         | 
| 402 | 
            +
            				return rb_frame_hash;
         | 
| 403 | 
            +
            			}
         | 
| 404 | 
            +
            			else if ( c_return_all_frames == TRUE )	{
         | 
| 405 | 
            +
            				rb_ary_push(	rb_frame_hashes_array,
         | 
| 406 | 
            +
            								rb_frame_hash );
         | 
| 407 | 
            +
            				return rb_frame_hashes_array;
         | 
| 408 | 
            +
            			}
         | 
| 409 | 
            +
            			else {
         | 
| 410 | 
            +
            				return Qtrue;							
         | 
| 411 | 
            +
            			}
         | 
| 172 412 | 
             
            		}
         | 
| 173 413 | 
             
            		c_current_context_frame = RUBY_VM_PREVIOUS_CONTROL_FRAME( c_current_context_frame );		
         | 
| 174 414 | 
             
            	}
         | 
| 175 | 
            -
             | 
| 415 | 
            +
            	
         | 
| 416 | 
            +
            	if (	c_return_all_frames == TRUE
         | 
| 417 | 
            +
            		&&	RARRAY_LEN( rb_frame_hashes_array ) > 0 ) {
         | 
| 418 | 
            +
            		return rb_frame_hashes_array;
         | 
| 419 | 
            +
            	}
         | 
| 176 420 | 
             
            	//	if we finish iterating frames and still have items in the array, return false
         | 
| 177 | 
            -
            	if ( RARRAY_LEN( rb_tracking_array ) > 0 )	{
         | 
| 421 | 
            +
            	else if ( RARRAY_LEN( rb_tracking_array ) > 0 )	{
         | 
| 178 422 | 
             
            		return Qfalse;
         | 
| 179 423 | 
             
            	}
         | 
| 180 | 
            -
            	
         | 
| 181 424 | 
             
            	//	otherwise, return true
         | 
| 182 | 
            -
            	 | 
| 425 | 
            +
            	else if ( c_return_frame == TRUE )	{
         | 
| 426 | 
            +
            		return rb_frame_hash;
         | 
| 427 | 
            +
            	}
         | 
| 428 | 
            +
            	else {
         | 
| 429 | 
            +
            		return Qtrue;							
         | 
| 430 | 
            +
            	}
         | 
| 431 | 
            +
            	//	we don't get here
         | 
| 432 | 
            +
            	return Qnil;
         | 
| 433 | 
            +
            }
         | 
| 434 | 
            +
             | 
| 435 | 
            +
            /***************************************
         | 
| 436 | 
            +
             *  Kernel.backtrace_includes_one_of?  *
         | 
| 437 | 
            +
             **************************************/
         | 
| 438 | 
            +
             | 
| 439 | 
            +
            /*
         | 
| 440 | 
            +
             * call-seq:
         | 
| 441 | 
            +
             *   Kernel.backtrace_includes_one_of?( method_or_object, ... ) -> true or false
         | 
| 442 | 
            +
             *   Kernel.backtrace_includes_one_of?( number_of_frames, method_or_object, ... ) -> true or false
         | 
| 443 | 
            +
             *
         | 
| 444 | 
            +
             * Returns whether one of the specified methods or objects or classes are in the current backtrace context.
         | 
| 445 | 
            +
             * Kernel.backtrace_includes_one_of? begins with the prior frame, so asking if the backtrace includes the current method
         | 
| 446 | 
            +
             * will only report true if the current method is part of the earlier call chain.
         | 
| 447 | 
            +
             */
         | 
| 448 | 
            +
            VALUE rb_RPRuby_Sender_Kernel_backtrace_includes_one_of(	int		argc,
         | 
| 449 | 
            +
            															VALUE*	args,
         | 
| 450 | 
            +
            															VALUE	rb_self )	{
         | 
| 451 | 
            +
             | 
| 452 | 
            +
            	//	method implemented as special case of backtrace_includes?
         | 
| 453 | 
            +
            	
         | 
| 454 | 
            +
            	//	create a new array starting with Qtrue and then followed by args
         | 
| 455 | 
            +
            	VALUE		c_methods_array[ argc + 1 ];
         | 
| 456 | 
            +
            	c_methods_array[ 0 ] = Qnil;
         | 
| 457 | 
            +
            	int	c_which_arg;
         | 
| 458 | 
            +
            	for ( c_which_arg = 0 ; c_which_arg < argc ; c_which_arg++ )	{
         | 
| 459 | 
            +
            		c_methods_array[ c_which_arg + 1 ] = args[ c_which_arg ];
         | 
| 460 | 
            +
            	}
         | 
| 461 | 
            +
            	return rb_RPRuby_Sender_Kernel_backtrace_includes(	argc + 1,
         | 
| 462 | 
            +
            														c_methods_array,
         | 
| 463 | 
            +
            														rb_self );
         | 
| 464 | 
            +
            }
         | 
| 465 | 
            +
             | 
| 466 | 
            +
            /*********************************
         | 
| 467 | 
            +
             *  Kernel.backtrace_frame_with  *
         | 
| 468 | 
            +
             ********************************/
         | 
| 469 | 
            +
             | 
| 470 | 
            +
            /*
         | 
| 471 | 
            +
             * call-seq:
         | 
| 472 | 
            +
             *   Kernel.backtrace_frame_with( method_or_object, ... ) -> true or false
         | 
| 473 | 
            +
             *   Kernel.backtrace_frame_with( number_of_frames, method_or_object, ... ) -> true or false
         | 
| 474 | 
            +
             *
         | 
| 475 | 
            +
             * Returns first frame matching specifications, which work like Kernel.backtrace_includes?. 
         | 
| 476 | 
            +
             * Kernel.backtrace_includes_one_of? begins with the prior frame, so asking if the backtrace includes the current method
         | 
| 477 | 
            +
             * will only report true if the current method is part of the earlier call chain.
         | 
| 478 | 
            +
             */
         | 
| 479 | 
            +
            VALUE rb_RPRuby_Sender_Kernel_backtrace_frame_with(	int		argc,
         | 
| 480 | 
            +
            													VALUE*	args,
         | 
| 481 | 
            +
            													VALUE	rb_self )	{
         | 
| 482 | 
            +
            	
         | 
| 483 | 
            +
            	//	create a new array starting with Qtrue and then followed by args
         | 
| 484 | 
            +
            	VALUE		c_methods_array[ argc + 1 ];
         | 
| 485 | 
            +
            	//	Qfalse tells backtrace_includes to return frame hash instead of true/false
         | 
| 486 | 
            +
            	c_methods_array[ 0 ] = Qfalse;
         | 
| 487 | 
            +
            	int	c_which_arg;
         | 
| 488 | 
            +
            	for ( c_which_arg = 0 ; c_which_arg < argc ; c_which_arg++ )	{
         | 
| 489 | 
            +
            		c_methods_array[ c_which_arg + 1 ] = args[ c_which_arg ];
         | 
| 490 | 
            +
            	}
         | 
| 491 | 
            +
            	return rb_RPRuby_Sender_Kernel_backtrace_includes_one_of(	argc + 1,
         | 
| 492 | 
            +
            																c_methods_array,
         | 
| 493 | 
            +
            																rb_self );	
         | 
| 494 | 
            +
            }
         | 
| 495 | 
            +
             | 
| 496 | 
            +
            /**********************************
         | 
| 497 | 
            +
             *  Kernel.backtrace_frames_with  *
         | 
| 498 | 
            +
             *********************************/
         | 
| 499 | 
            +
             | 
| 500 | 
            +
            /*
         | 
| 501 | 
            +
             * call-seq:
         | 
| 502 | 
            +
             *   Kernel.backtrace_frames_with( method_or_object, ... ) -> true or false
         | 
| 503 | 
            +
             *   Kernel.backtrace_frames_with( number_of_frames, method_or_object, ... ) -> true or false
         | 
| 504 | 
            +
             *
         | 
| 505 | 
            +
             * Returns all frames matching specifications, which work like Kernel.backtrace_includes?. 
         | 
| 506 | 
            +
             * Kernel.backtrace_includes_one_of? begins with the prior frame, so asking if the backtrace includes the current method
         | 
| 507 | 
            +
             * will only report true if the current method is part of the earlier call chain.
         | 
| 508 | 
            +
             */
         | 
| 509 | 
            +
            VALUE rb_RPRuby_Sender_Kernel_backtrace_frames_with(	int		argc,
         | 
| 510 | 
            +
            														VALUE*	args,
         | 
| 511 | 
            +
            														VALUE	rb_self )	{
         | 
| 512 | 
            +
            	
         | 
| 513 | 
            +
            	
         | 
| 514 | 
            +
            	//	create a new array starting with Qtrue and then followed by args
         | 
| 515 | 
            +
            	VALUE		c_methods_array[ argc + 1 ];
         | 
| 516 | 
            +
            	//	Qtrue tells backtrace_includes to return all frame hashes specified instead of the first
         | 
| 517 | 
            +
            	c_methods_array[ 0 ] = Qtrue;
         | 
| 518 | 
            +
            	int	c_which_arg;
         | 
| 519 | 
            +
            	for ( c_which_arg = 0 ; c_which_arg < argc ; c_which_arg++ )	{
         | 
| 520 | 
            +
            		c_methods_array[ c_which_arg + 1 ] = args[ c_which_arg ];
         | 
| 521 | 
            +
            	}
         | 
| 522 | 
            +
            	return rb_RPRuby_Sender_Kernel_backtrace_includes(	argc + 1,
         | 
| 523 | 
            +
            														c_methods_array,
         | 
| 524 | 
            +
            														rb_self );	
         | 
| 183 525 | 
             
            }
         | 
| 184 526 |  | 
| 527 | 
            +
            /***************************************************************************************************************************************************************
         | 
| 528 | 
            +
            ****************************************************************************************************************************************************************
         | 
| 529 | 
            +
            													Internal Methods
         | 
| 530 | 
            +
            ****************************************************************************************************************************************************************
         | 
| 531 | 
            +
            ***************************************************************************************************************************************************************/
         | 
| 532 | 
            +
             | 
| 185 533 | 
             
            /**********************************
         | 
| 186 534 | 
             
             *  backtraceHashForControlFrame  *
         | 
| 187 535 | 
             
             *********************************/
         | 
| @@ -214,6 +562,7 @@ VALUE rb_RPRuby_Sender_Kernel_internal_backtraceHashForControlFrame(	rb_control_ | |
| 214 562 |  | 
| 215 563 | 
             
            			//	get name of instruction sequence
         | 
| 216 564 | 
             
            			rb_method_name			=	ID2SYM( rb_intern( StringValuePtr( iseq->name ) ) );				
         | 
| 565 | 
            +
            			rb_object_for_frame	=	( *c_current_frame )->self;
         | 
| 217 566 | 
             
            		}
         | 
| 218 567 | 
             
            	}
         | 
| 219 568 | 
             
            	else if ( RUBYVM_CFUNC_FRAME_P( *c_current_frame ) ) {
         | 
| @@ -221,6 +570,68 @@ VALUE rb_RPRuby_Sender_Kernel_internal_backtraceHashForControlFrame(	rb_control_ | |
| 221 570 | 
             
            		//	get name of method
         | 
| 222 571 | 
             
            		c_method_name				=	rb_id2name( ( *c_current_frame )->method_id );
         | 
| 223 572 | 
             
            		rb_method_name				=	( c_method_name == NULL ? Qnil : ID2SYM( rb_intern( c_method_name ) ) );
         | 
| 573 | 
            +
            		rb_object_for_frame	=	( *c_current_frame )->self;		
         | 
| 574 | 
            +
            	}
         | 
| 575 | 
            +
            	//	we have to test this case - it works for blocks but there may be other cases too
         | 
| 576 | 
            +
            	else if (	( *c_current_frame )->block_iseq != 0
         | 
| 577 | 
            +
            			 &&	( *c_current_frame )->pc == 0)	{
         | 
| 578 | 
            +
            	
         | 
| 579 | 
            +
            		//	If we got here we have a fiber
         | 
| 580 | 
            +
            		//	There doesn't seem to be much that we can tell about a fiber's context
         | 
| 581 | 
            +
            			
         | 
| 582 | 
            +
            		VALUE			rb_current_fiber	=	rb_fiber_current();
         | 
| 583 | 
            +
            		rb_fiber_t*		c_current_fiber		=	NULL;
         | 
| 584 | 
            +
             | 
| 585 | 
            +
            		GetFiberPtr(	rb_current_fiber, 
         | 
| 586 | 
            +
            						c_current_fiber);
         | 
| 587 | 
            +
            						
         | 
| 588 | 
            +
            		rb_context_t*	c_context			=	& c_current_fiber->cont;
         | 
| 589 | 
            +
            		
         | 
| 590 | 
            +
            //		rb_block_t*	c_blockptr = RUBY_VM_GET_BLOCK_PTR_IN_CFP( *c_current_frame );
         | 
| 591 | 
            +
            		 
         | 
| 592 | 
            +
            		rb_object_for_frame	=	( *c_current_frame )->self;
         | 
| 593 | 
            +
            		
         | 
| 594 | 
            +
            		//	get sourcefile name and set in hash
         | 
| 595 | 
            +
            		rb_sourcefile_name		=	Qnil;
         | 
| 596 | 
            +
             | 
| 597 | 
            +
            		//	get sourcefile line and set in hash
         | 
| 598 | 
            +
            		rb_sourcefile_line		=	Qnil;
         | 
| 599 | 
            +
            		
         | 
| 600 | 
            +
            		//	get name of instruction sequence
         | 
| 601 | 
            +
            		rb_method_name			=	rb_str_new2( "<Fiber>" );		
         | 
| 602 | 
            +
            		
         | 
| 603 | 
            +
            		//	if we have a fiber we also include its ruby reference since we have so little other context
         | 
| 604 | 
            +
            		rb_hash_aset(	rb_frame_hash,
         | 
| 605 | 
            +
            						ID2SYM( rb_intern( "fiber" ) ),
         | 
| 606 | 
            +
            						c_context->self );
         | 
| 607 | 
            +
            		
         | 
| 608 | 
            +
            		//	The one time that we know a fiber is in use in the Ruby base is with Enumerators
         | 
| 609 | 
            +
            		//	For now we will handle that with a special case
         | 
| 610 | 
            +
            		
         | 
| 611 | 
            +
            		VALUE	rb_enumerator_class	=	rb_const_get(	rb_cObject,
         | 
| 612 | 
            +
            														rb_intern( "Enumerator" ) );
         | 
| 613 | 
            +
            		
         | 
| 614 | 
            +
            		VALUE	rb_object_for_frame_klass	=	( ( TYPE( rb_object_for_frame ) == T_CLASS ) ? rb_object_for_frame : rb_funcall( rb_object_for_frame, rb_intern( "class" ), 0 ) );
         | 
| 615 | 
            +
             | 
| 616 | 
            +
            		VALUE	rb_ancestors	=	rb_funcall(	rb_object_for_frame_klass,
         | 
| 617 | 
            +
            												rb_intern( "ancestors" ),
         | 
| 618 | 
            +
            												0 );
         | 
| 619 | 
            +
            		
         | 
| 620 | 
            +
            		if ( rb_ary_includes(	rb_ancestors,
         | 
| 621 | 
            +
            								rb_enumerator_class ) )	{
         | 
| 622 | 
            +
            			
         | 
| 623 | 
            +
            			struct enumerator* c_enumerator		=	enumerator_ptr( rb_object_for_frame );
         | 
| 624 | 
            +
            			
         | 
| 625 | 
            +
            			rb_object_for_frame	=	c_enumerator->obj;
         | 
| 626 | 
            +
            			rb_method_name		=	ID2SYM( c_enumerator->meth );			
         | 
| 627 | 
            +
            		}
         | 
| 628 | 
            +
            		
         | 
| 629 | 
            +
            	}
         | 
| 630 | 
            +
            	else if (	( *c_current_frame )->block_iseq == 0
         | 
| 631 | 
            +
            			 &&	( *c_current_frame )->pc == 0)	{
         | 
| 632 | 
            +
            		//	this happens after we had a fiber and we try to go up - which doesn't make sense with a fiber
         | 
| 633 | 
            +
            		//	not sure what we want to do here, if anything
         | 
| 634 | 
            +
            		return Qnil;
         | 
| 224 635 | 
             
            	}
         | 
| 225 636 | 
             
            	else {
         | 
| 226 637 | 
             
            		//	The third possibility is that we have an iseq frame with nil params for what we want
         | 
| @@ -239,7 +650,6 @@ VALUE rb_RPRuby_Sender_Kernel_internal_backtraceHashForControlFrame(	rb_control_ | |
| 239 650 |  | 
| 240 651 | 
             
            	//	Push values to return hash
         | 
| 241 652 |  | 
| 242 | 
            -
            	rb_object_for_frame	=	( *c_current_frame )->self;
         | 
| 243 653 | 
             
            	rb_hash_aset(	rb_frame_hash,
         | 
| 244 654 | 
             
            					ID2SYM( rb_intern( "object" ) ),
         | 
| 245 655 | 
             
            					rb_object_for_frame );
         | 
    
        data/ext/sender/rb_Kernel.h
    CHANGED
    
    | @@ -11,8 +11,21 @@ | |
| 11 11 | 
             
            	VALUE rb_RPRuby_Sender_Kernel_backtrace(	int		argc,
         | 
| 12 12 | 
             
            											VALUE*	args,
         | 
| 13 13 | 
             
            											VALUE	rb_self );
         | 
| 14 | 
            +
            	VALUE rb_RPRuby_Sender_Kernel_each_backtrace_frame(	int		argc,
         | 
| 15 | 
            +
            													   VALUE*	args,
         | 
| 16 | 
            +
            													   VALUE	rb_self );
         | 
| 14 17 | 
             
            	VALUE rb_RPRuby_Sender_Kernel_backtrace_includes(	int	argc,
         | 
| 15 18 | 
             
            														VALUE*	args,
         | 
| 16 19 | 
             
            														VALUE	rb_self );
         | 
| 17 | 
            -
             | 
| 20 | 
            +
            	VALUE rb_RPRuby_Sender_Kernel_backtrace_includes_one_of(	int		argc,
         | 
| 21 | 
            +
            																VALUE*	args,
         | 
| 22 | 
            +
            																VALUE	rb_self );
         | 
| 23 | 
            +
            	VALUE rb_RPRuby_Sender_Kernel_backtrace_frame_with(	int		argc,
         | 
| 24 | 
            +
            														VALUE*	args,
         | 
| 25 | 
            +
            														VALUE	rb_self );
         | 
| 26 | 
            +
            	VALUE rb_RPRuby_Sender_Kernel_backtrace_frames_with(	int		argc,
         | 
| 27 | 
            +
            															VALUE*	args,
         | 
| 28 | 
            +
            															VALUE	rb_self );
         | 
| 29 | 
            +
            	
         | 
| 30 | 
            +
            	
         | 
| 18 31 | 
             
            #endif
         | 
    
        data/lib/VERSION.rdoc
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            1. | 
| 1 | 
            +
            1.5
         | 
    
        data/lib/sender/sender.bundle
    CHANGED
    
    | Binary file | 
    
        data/sender.gemspec
    CHANGED
    
    | @@ -2,14 +2,16 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            Gem::Specification.new do |s|
         | 
| 4 4 | 
             
              s.name = %q{sender}
         | 
| 5 | 
            -
              s.version = "1. | 
| 5 | 
            +
              s.version = "1.5"
         | 
| 6 6 |  | 
| 7 7 | 
             
              s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
         | 
| 8 8 | 
             
              s.authors = ["Asher"]
         | 
| 9 | 
            -
              s.date = %q{2010- | 
| 10 | 
            -
              s.description = %q{Adds :__sender__ and :__caller__ to the built-in :__callee__ and :__method__ methods in Ruby 1.9.1 | 
| 11 | 
            -
             | 
| 12 | 
            -
             | 
| 9 | 
            +
              s.date = %q{2010-07-09}
         | 
| 10 | 
            +
              s.description = %q{Adds :__sender__ and :__caller__ to the built-in :__callee__ and :__method__ methods in Ruby 1.9.1.
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            Also provides object-oriented :backtrace supporting n-levels backward, :each_backtrace_frame for iteration, :backtrace_includes?, 
         | 
| 13 | 
            +
            and :backtrace_includes_one_of? for context inspection, and :backtrace_frame_with and :backtrace_frames_with, which return
         | 
| 14 | 
            +
            matching frame information for the frame(s) matching the given description.}
         | 
| 13 15 | 
             
              s.email = ["asher@ridiculouspower.com"]
         | 
| 14 16 | 
             
              s.extensions = ["ext/sender/extconf.rb"]
         | 
| 15 17 | 
             
              s.extra_rdoc_files = ["Manifest.txt", "CHANGELOG.rdoc", "README.rdoc", "VERSION.rdoc"]
         | 
| @@ -19,7 +21,7 @@ which allows contents of the backtrace to be queried.} | |
| 19 21 | 
             
              s.require_paths = ["lib"]
         | 
| 20 22 | 
             
              s.rubyforge_project = %q{asher}
         | 
| 21 23 | 
             
              s.rubygems_version = %q{1.3.7}
         | 
| 22 | 
            -
              s.summary = %q{Adds :__sender__ and :__caller__ to the built-in :__callee__ and :__method__ methods in Ruby 1.9.1 | 
| 24 | 
            +
              s.summary = %q{Adds :__sender__ and :__caller__ to the built-in :__callee__ and :__method__ methods in Ruby 1.9.1}
         | 
| 23 25 | 
             
              s.test_files = ["test/test_sender.rb"]
         | 
| 24 26 |  | 
| 25 27 | 
             
              if s.respond_to? :specification_version then
         | 
    
        metadata
    CHANGED
    
    | @@ -1,13 +1,12 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification 
         | 
| 2 2 | 
             
            name: sender
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            -
              hash:  | 
| 4 | 
            +
              hash: 5
         | 
| 5 5 | 
             
              prerelease: false
         | 
| 6 6 | 
             
              segments: 
         | 
| 7 7 | 
             
              - 1
         | 
| 8 | 
            -
              -  | 
| 9 | 
            -
               | 
| 10 | 
            -
              version: 1.4.3
         | 
| 8 | 
            +
              - 5
         | 
| 9 | 
            +
              version: "1.5"
         | 
| 11 10 | 
             
            platform: ruby
         | 
| 12 11 | 
             
            authors: 
         | 
| 13 12 | 
             
            - Asher
         | 
| @@ -15,7 +14,7 @@ autorequire: | |
| 15 14 | 
             
            bindir: bin
         | 
| 16 15 | 
             
            cert_chain: []
         | 
| 17 16 |  | 
| 18 | 
            -
            date: 2010- | 
| 17 | 
            +
            date: 2010-07-09 00:00:00 -04:00
         | 
| 19 18 | 
             
            default_executable: 
         | 
| 20 19 | 
             
            dependencies: 
         | 
| 21 20 | 
             
            - !ruby/object:Gem::Dependency 
         | 
| @@ -65,9 +64,11 @@ dependencies: | |
| 65 64 | 
             
              type: :development
         | 
| 66 65 | 
             
              version_requirements: *id003
         | 
| 67 66 | 
             
            description: |-
         | 
| 68 | 
            -
              Adds :__sender__ and :__caller__ to the built-in :__callee__ and :__method__ methods in Ruby 1.9.1 | 
| 69 | 
            -
               | 
| 70 | 
            -
               | 
| 67 | 
            +
              Adds :__sender__ and :__caller__ to the built-in :__callee__ and :__method__ methods in Ruby 1.9.1.
         | 
| 68 | 
            +
              
         | 
| 69 | 
            +
              Also provides object-oriented :backtrace supporting n-levels backward, :each_backtrace_frame for iteration, :backtrace_includes?, 
         | 
| 70 | 
            +
              and :backtrace_includes_one_of? for context inspection, and :backtrace_frame_with and :backtrace_frames_with, which return
         | 
| 71 | 
            +
              matching frame information for the frame(s) matching the given description.
         | 
| 71 72 | 
             
            email: 
         | 
| 72 73 | 
             
            - asher@ridiculouspower.com
         | 
| 73 74 | 
             
            executables: []
         | 
| @@ -160,6 +161,6 @@ rubyforge_project: asher | |
| 160 161 | 
             
            rubygems_version: 1.3.7
         | 
| 161 162 | 
             
            signing_key: 
         | 
| 162 163 | 
             
            specification_version: 3
         | 
| 163 | 
            -
            summary: Adds :__sender__ and :__caller__ to the built-in :__callee__ and :__method__ methods in Ruby 1.9.1 | 
| 164 | 
            +
            summary: Adds :__sender__ and :__caller__ to the built-in :__callee__ and :__method__ methods in Ruby 1.9.1
         | 
| 164 165 | 
             
            test_files: 
         | 
| 165 166 | 
             
            - test/test_sender.rb
         |