From: Nathaniel Talbott Date: 2003-10-11T11:46:46+09:00 Subject: 'unexpected return' caused by extension This is a multi-part message in MIME format. ------=_NextPart_000_003F_01C38F80.53964A10 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit I'm writing my first (useful) Ruby extension, and I'm having issues. I'm sure it's just a combination of my lack of C knowledge and lack of Ruby knowledge, but I'd be extremely grateful for any pointers you might have. Basically, I'm trying to write a better, faster profiler. I've attached all of the interesting bits. When I run this on the tests from the most recent Ruby (actually, just trying to get help!), I get the following error: ntalbott@solomon:~/cvs/ruby/test$ ruby -v -I ~/nprof -rnprofit runner.rb --help /usr/local/lib/ruby/1.8/test/unit/autorunner.rb:10: unexpected return ruby 1.8.0 (2003-10-10) [i686-linux] Running it without the extension works as expected. I'm sure I'm doing something stupid... I promise to slap myself on the forehead when someone shows me what it is. Also, if you have any suggests regarding my C and/or Ruby/C style, please let me know. I'm looking to improve as much as possible. Thanks, Nathaniel <:((>< ------=_NextPart_000_003F_01C38F80.53964A10 Content-Type: application/octet-stream; name="nprofit.rb" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="nprofit.rb" require 'nprof'=0A= =0A= n =3D NProf.new=0A= at_exit {=0A= set_trace_func(nil)=0A= #n.print_report=0A= }=0A= set_trace_func(n.method(:callback).to_proc)=0A= ------=_NextPart_000_003F_01C38F80.53964A10 Content-Type: application/octet-stream; name="nprof.rb" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="nprof.rb" require 'nprofext'=0A= =0A= class NProf=0A= class MethodInfo=0A= attr_reader :calls, :children=0A= =0A= def name=0A= sep =3D (@klass.kind_of?(Module) ? "." : "#")=0A= "#@klass#{sep}#@id"=0A= end=0A= =0A= def utime=0A= @times.utime=0A= end=0A= =0A= def stime=0A= @times.stime=0A= end=0A= end=0A= =0A= COLUMN_SEPARATOR =3D " "=0A= def print_report(out=3DSTDOUT)=0A= out.puts ["calls", "utime", "stime", "child_count", = "name"].join(COLUMN_SEPARATOR)=0A= @method_info.values.each do |m|=0A= out.printf((["%5d", "%5.2f", "%5.2f", "%11d", = "%s\n"].join(COLUMN_SEPARATOR)), m.calls, m.utime, m.stime, = m.children.size, m.name)=0A= end=0A= end=0A= end=0A= ------=_NextPart_000_003F_01C38F80.53964A10 Content-Type: application/octet-stream; name="nprofext.c" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="nprofext.c" #include "ruby.h"=0A= =0A= /*=0A= #define DEBUG(message) printf(message)=0A= #define DEBUG_P(value) rb_p(value)=0A= =0A= #define DEBUG(message) =0A= #define DEBUG_P(value) =0A= */=0A= =0A= VALUE cNProf;=0A= VALUE cNProf_MethodInfo;=0A= =0A= static VALUE mi_initialize(VALUE self, VALUE klass, VALUE id) {=0A= VALUE S_Tms =3D rb_const_get(rb_cStruct, rb_intern("Tms"));=0A= =0A= rb_iv_set(self, "@klass", klass);=0A= rb_iv_set(self, "@id", id);=0A= rb_iv_set(self, "@times", rb_struct_new(S_Tms, = rb_float_new((double)0), rb_float_new((double)0)));=0A= rb_iv_set(self, "@children_times", rb_struct_new(S_Tms, = rb_float_new((double)0), rb_float_new((double)0)));=0A= rb_iv_set(self, "@children", rb_hash_new());=0A= rb_iv_set(self, "@calls", INT2FIX(0));=0A= }=0A= =0A= double mi_sub_times(VALUE first, VALUE second) {=0A= double utime, stime;=0A= VALUE difference;=0A= VALUE name =3D rb_str_new2("utime");=0A= utime =3D NUM2DBL(rb_struct_aref(first, name)) - = NUM2DBL(rb_struct_aref(second, name));=0A= name =3D rb_str_new2("stime");=0A= stime =3D NUM2DBL(rb_struct_aref(first, name)) - = NUM2DBL(rb_struct_aref(second, name));=0A= difference =3D rb_struct_new(rb_const_get(rb_cStruct, = rb_intern("Tms")), rb_float_new(utime), rb_float_new(stime), = rb_float_new((double)0), rb_float_new((double)0));=0A= return difference;=0A= }=0A= =0A= double mi_add_times(VALUE first, VALUE second) {=0A= double utime, stime;=0A= VALUE name =3D rb_str_new2("utime");=0A= utime =3D NUM2DBL(rb_struct_aref(first, name)) + = NUM2DBL(rb_struct_aref(second, name));=0A= name =3D rb_str_new2("stime");=0A= stime =3D NUM2DBL(rb_struct_aref(first, name)) + = NUM2DBL(rb_struct_aref(second, name));=0A= return rb_struct_new(rb_const_get(rb_cStruct, rb_intern("Tms")), = rb_float_new(utime), rb_float_new(stime), rb_float_new((double)0), = rb_float_new((double)0));=0A= }=0A= =0A= void mi_add_in_times(VALUE mi, VALUE difference) {=0A= rb_iv_set(mi, "@times", mi_add_times(rb_iv_get(mi, "@times"), = difference));=0A= }=0A= =0A= void mi_finish_child(VALUE parent, VALUE child_key, VALUE child_times) {=0A= rb_iv_set(parent, "@children_times", mi_add_times(rb_iv_get(parent, = "@children_times"), child_times));=0A= rb_hash_aset(rb_iv_get(parent, "@children"), child_key, Qtrue);=0A= }=0A= =0A= static VALUE nprof_initialize(VALUE self) {=0A= rb_iv_set(self, "@stack", rb_ary_new());=0A= rb_iv_set(self, "@method_info", rb_hash_new());=0A= }=0A= =0A= static VALUE nprof_rattr_stack(VALUE self) {=0A= return rb_iv_get(self, "@stack");=0A= }=0A= =0A= static VALUE nprof_rattr_method_info(VALUE self) {=0A= return rb_iv_get(self, "@method_info");=0A= }=0A= =0A= VALUE nprof_start(VALUE args) {=0A= VALUE self =3D rb_ary_entry(args, 0);=0A= VALUE klass =3D rb_ary_entry(args, 1);=0A= VALUE id =3D rb_ary_entry(args, 2);=0A= VALUE stack =3D rb_iv_get(self, "@stack");=0A= VALUE now =3D rb_proc_times(rb_mProcess);=0A= VALUE method_info_hash, method_info_key, method_info, ary;=0A= =0A= ary =3D rb_ary_entry(stack, RARRAY(stack)->len - 1);=0A= =0A= method_info_hash =3D rb_iv_get(self, "@method_info");=0A= method_info_key =3D rb_ary_new3(2, klass, id);=0A= method_info =3D rb_hash_aref(method_info_hash, method_info_key);=0A= if(!RTEST(method_info)) {=0A= method_info =3D rb_funcall(cNProf_MethodInfo, rb_intern("new"), 2, = klass, id);=0A= rb_hash_aset(method_info_hash, method_info_key, method_info);=0A= }=0A= rb_iv_set(method_info, "@calls", = INT2FIX(NUM2INT(rb_iv_get(method_info, "@calls")) + 1));=0A= rb_ary_push(stack, rb_ary_new3(2, method_info, now));=0A= return Qnil;=0A= }=0A= =0A= VALUE nprof_finish(VALUE args) {=0A= VALUE self =3D rb_ary_entry(args, 0);=0A= VALUE klass =3D rb_ary_entry(args, 1);=0A= VALUE id =3D rb_ary_entry(args, 2);=0A= VALUE stack =3D rb_iv_get(self, "@stack");=0A= VALUE now =3D rb_proc_times(rb_mProcess);=0A= VALUE method_info_key, method_info, ary, then, difference;=0A= =0A= ary =3D rb_ary_pop(stack);=0A= if(!RTEST(ary))=0A= return Qnil;=0A= =0A= method_info =3D rb_ary_entry(ary, 0);=0A= then =3D rb_ary_entry(ary, 1);=0A= =0A= difference =3D mi_sub_times(now, then);=0A= mi_add_in_times(method_info, difference);=0A= =0A= ary =3D rb_ary_entry(stack, RARRAY(stack)->len - 1);=0A= if(RTEST(ary)) {=0A= method_info_key =3D rb_ary_new3(2, klass, id);=0A= mi_finish_child(rb_ary_entry(ary, 0), method_info_key, difference);=0A= }=0A= return Qnil;=0A= }=0A= =0A= VALUE nprof_err(VALUE args, VALUE error) {=0A= rb_funcall(rb_mKernel, rb_intern("set_trace_func"), 1, Qnil);=0A= rb_p(args);=0A= rb_p(error);=0A= return Qnil;=0A= }=0A= =0A= static VALUE nprof_callback(VALUE self, VALUE event, VALUE file, VALUE = line, VALUE id, VALUE binding, VALUE klass) {=0A= char* event_string =3D STR2CSTR(event);=0A= VALUE args, eargs;=0A= =0A= if(!strcmp(event_string, "call") || !strcmp(event_string, "c-call")) {=0A= args =3D rb_ary_new3(3, self, klass, id);=0A= eargs =3D rb_ary_new3(3, line, klass, id);=0A= rb_rescue(nprof_start, args, nprof_err, eargs);=0A= } else if(!strcmp(event_string, "return") || !strcmp(event_string, = "c-return")) {=0A= args =3D rb_ary_new3(3, self, klass, id);=0A= eargs =3D rb_ary_new3(3, line, klass, id);=0A= rb_rescue(nprof_finish, args, nprof_err, eargs);=0A= }=0A= =0A= return Qnil;=0A= }=0A= =0A= void Init_nprofext() {=0A= cNProf =3D rb_define_class("NProf", rb_cObject);=0A= rb_define_method(cNProf, "initialize", nprof_initialize, 0);=0A= rb_define_method(cNProf, "stack", nprof_rattr_stack, 0);=0A= rb_define_method(cNProf, "method_info", nprof_rattr_method_info, 0);=0A= rb_define_method(cNProf, "callback", nprof_callback, 6);=0A= =0A= cNProf_MethodInfo =3D rb_define_class_under(cNProf, "MethodInfo", = rb_cObject);=0A= rb_define_method(cNProf_MethodInfo, "initialize", mi_initialize, 2);=0A= }=0A= ------=_NextPart_000_003F_01C38F80.53964A10 Content-Type: application/octet-stream; name="extconf.rb" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="extconf.rb" require 'mkmf'=0A= =0A= create_makefile("nprofext")=0A= ------=_NextPart_000_003F_01C38F80.53964A10--