/* error.c Ruby/GSL: Ruby extension library for GSL (GNU Scientific Library) (C) Copyright 2001-2006 by Yoshiki Tsunesada Ruby/GSL is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY. */ #include "include/rb_gsl.h" #include #include "include/rb_gsl_array.h" #include "include/rb_gsl_common.h" #include "include/rb_gsl_function.h" static VALUE eHandler; static VALUE cgsl_error[35]; static VALUE *pgsl_error; static void Init_rb_gsl_define_GSL_CONST(VALUE module); void rb_gsl_error_handler(const char *reason, const char *file, int line, int gsl_errno); static void rb_gsl_my_error_handler(const char *reason, const char *file, int line, int gsl_errno); void rb_gsl_error_handler(const char *reason, const char *file, int line, int gsl_errno) { const char *emessage = gsl_strerror(gsl_errno); rb_raise(pgsl_error[gsl_errno], "Ruby/GSL error code %d, %s (file %s, line %d), %s", gsl_errno, reason, file, line, emessage); } static void rb_gsl_my_error_handler(const char *reason, const char *file, int line, int gsl_errno) { VALUE vreason, vfile; VALUE vline, verrno; vreason = rb_str_new2(reason); vfile = rb_str_new2(file); vline = INT2FIX(line); verrno = INT2FIX(gsl_errno); rb_funcall(eHandler, RBGSL_ID_call, 4, vreason, vfile, vline, verrno); } static VALUE rb_gsl_set_error_handler(int argc, VALUE *argv, VALUE module) { if (rb_block_given_p()) { eHandler = rb_block_proc(); gsl_set_error_handler(&rb_gsl_my_error_handler); return Qtrue; } switch (argc) { case 0: gsl_set_error_handler(&rb_gsl_error_handler); return Qtrue; break; case 1: CHECK_PROC(argv[0]); eHandler = argv[0]; gsl_set_error_handler(&rb_gsl_my_error_handler); return Qtrue; break; default: rb_raise(rb_eArgError, "too many arguments (%d for 0 or 1 Proc)", argc); break; } } static VALUE rb_gsl_set_default_error_handler(VALUE module) { gsl_set_error_handler(&rb_gsl_error_handler); return Qtrue; } static void rb_gsl_define_exceptions(VALUE module) { VALUE mgsl_error; mgsl_error = rb_define_module_under(module, "ERROR"); pgsl_error = &cgsl_error[2]; pgsl_error[-2] = rb_define_class_under(mgsl_error, "CONTINUE", rb_cFixnum); pgsl_error[-1] = rb_define_class_under(mgsl_error, "FAILURE", rb_eRuntimeError); pgsl_error[0] = rb_define_class_under(mgsl_error, "SUCCESS", rb_cFixnum); pgsl_error[1] = rb_define_class_under(mgsl_error, "EDOM", rb_eRangeError); pgsl_error[2] = rb_define_class_under(mgsl_error, "ERANGE", rb_eRangeError); pgsl_error[3] = rb_define_class_under(mgsl_error, "EFAULT", rb_eRuntimeError); pgsl_error[4] = rb_define_class_under(mgsl_error, "EINVAL", rb_eIndexError); pgsl_error[5] = rb_define_class_under(mgsl_error, "EFAILED", rb_eRuntimeError); pgsl_error[6] = rb_define_class_under(mgsl_error, "EFACTOR", rb_eRuntimeError); pgsl_error[7] = rb_define_class_under(mgsl_error, "ESANITY", rb_eRuntimeError); pgsl_error[8] = rb_define_class_under(mgsl_error, "ENOMEM", rb_eNoMemError); pgsl_error[9] = rb_define_class_under(mgsl_error, "EBADFUNC", rb_eRuntimeError); pgsl_error[10] = rb_define_class_under(mgsl_error, "ERUNAWAY", rb_eRuntimeError); pgsl_error[11] = rb_define_class_under(mgsl_error, "EMAXITER", rb_eRuntimeError); pgsl_error[12] = rb_define_class_under(mgsl_error, "EZERODIV", rb_eZeroDivError); pgsl_error[13] = rb_define_class_under(mgsl_error, "EBADTOL", rb_eRuntimeError); pgsl_error[14] = rb_define_class_under(mgsl_error, "ETOL", rb_eRuntimeError); pgsl_error[15] = rb_define_class_under(mgsl_error, "EUNDRFLW", rb_eRangeError); pgsl_error[16] = rb_define_class_under(mgsl_error, "EOVRFLW", rb_eRangeError); pgsl_error[17] = rb_define_class_under(mgsl_error, "ELOSS", rb_eRuntimeError); pgsl_error[18] = rb_define_class_under(mgsl_error, "EROUND", rb_eRuntimeError); pgsl_error[19] = rb_define_class_under(mgsl_error, "EBADLEN", rb_eIndexError); pgsl_error[20] = rb_define_class_under(mgsl_error, "ENOTSQR", rb_eRuntimeError); pgsl_error[21] = rb_define_class_under(mgsl_error, "ESING", rb_eRuntimeError); pgsl_error[22] = rb_define_class_under(mgsl_error, "EDIVERGE", rb_eRuntimeError); pgsl_error[23] = rb_define_class_under(mgsl_error, "EUNSUP", rb_eRuntimeError); pgsl_error[24] = rb_define_class_under(mgsl_error, "EUNIMPL", rb_eNotImpError); pgsl_error[25] = rb_define_class_under(mgsl_error, "ECACHE", rb_eRuntimeError); pgsl_error[26] = rb_define_class_under(mgsl_error, "ETABLE", rb_eRuntimeError); pgsl_error[27] = rb_define_class_under(mgsl_error, "ENOPROG", rb_eRuntimeError); pgsl_error[28] = rb_define_class_under(mgsl_error, "ENOPROGJ", rb_eRuntimeError); pgsl_error[29] = rb_define_class_under(mgsl_error, "ETOLF", rb_eRuntimeError); pgsl_error[30] = rb_define_class_under(mgsl_error, "ETOLX", rb_eRuntimeError); pgsl_error[31] = rb_define_class_under(mgsl_error, "ETOLG", rb_eRuntimeError); pgsl_error[32] = rb_define_class_under(mgsl_error, "EOF", rb_eEOFError); } static void Init_rb_gsl_define_GSL_CONST(VALUE module) { rb_define_const(module, "SUCCESS", INT2FIX(GSL_SUCCESS)); rb_define_const(module, "FAILURE", INT2FIX(GSL_FAILURE)); rb_define_const(module, "CONTINUE", INT2FIX(GSL_CONTINUE)); rb_define_const(module, "EDOM", INT2FIX(GSL_EDOM)); rb_define_const(module, "ERANGE", INT2FIX(GSL_ERANGE)); rb_define_const(module, "EFAULT", INT2FIX(GSL_EFAULT)); rb_define_const(module, "EINVAL", INT2FIX(GSL_EINVAL)); rb_define_const(module, "EFAILED", INT2FIX(GSL_EFAILED)); rb_define_const(module, "EFACTOR", INT2FIX(GSL_EFACTOR)); rb_define_const(module, "ESANITY", INT2FIX(GSL_ESANITY)); rb_define_const(module, "ENOMEM", INT2FIX(GSL_ENOMEM)); rb_define_const(module, "EBADFUNC", INT2FIX(GSL_EBADFUNC)); rb_define_const(module, "ERUNAWAY", INT2FIX(GSL_ERUNAWAY)); rb_define_const(module, "EMAXITER", INT2FIX(GSL_EMAXITER)); rb_define_const(module, "EZERODIV", INT2FIX(GSL_EZERODIV)); rb_define_const(module, "EBADTOL", INT2FIX(GSL_EBADTOL)); rb_define_const(module, "ETOL", INT2FIX(GSL_ETOL)); rb_define_const(module, "EUNDRFLW", INT2FIX(GSL_EUNDRFLW)); rb_define_const(module, "EOVRFLW", INT2FIX(GSL_EOVRFLW)); rb_define_const(module, "ELOSS", INT2FIX(GSL_ELOSS)); rb_define_const(module, "EROUND", INT2FIX(GSL_EROUND)); rb_define_const(module, "EBADLEN", INT2FIX(GSL_EBADLEN)); rb_define_const(module, "ENOTSQR", INT2FIX(GSL_ENOTSQR)); rb_define_const(module, "ESING", INT2FIX(GSL_ESING)); rb_define_const(module, "EDIVERGE", INT2FIX(GSL_EDIVERGE)); rb_define_const(module, "EUNSUP", INT2FIX(GSL_EUNSUP)); rb_define_const(module, "EUNIMPL", INT2FIX(GSL_EUNIMPL)); rb_define_const(module, "ECACHE", INT2FIX(GSL_ECACHE)); rb_define_const(module, "ETABLE", INT2FIX(GSL_ETABLE)); rb_define_const(module, "ENOPROG", INT2FIX(GSL_ENOPROG)); rb_define_const(module, "ENOPROGJ", INT2FIX(GSL_ENOPROGJ)); rb_define_const(module, "ETOLF", INT2FIX(GSL_ETOLF)); rb_define_const(module, "ETOLX", INT2FIX(GSL_ETOLX)); rb_define_const(module, "ETOLG", INT2FIX(GSL_ETOLG)); rb_define_const(module, "EOF", INT2FIX(GSL_EOF)); } static VALUE rb_gsl_set_error_handler_off(VALUE module) { gsl_set_error_handler_off(); return Qtrue; } static void define_module_functions(VALUE module); static VALUE rb_gsl_strerror(VALUE obj, VALUE errn); static void define_module_functions(VALUE module) { rb_define_module_function(module, "set_error_handler_off", rb_gsl_set_error_handler_off, 0); rb_define_module_function(module, "strerror", rb_gsl_strerror, 1); rb_define_module_function(module, "set_error_handler", rb_gsl_set_error_handler, -1); rb_define_module_function(module, "set_default_error_handler", rb_gsl_set_default_error_handler, 0); } static VALUE rb_gsl_strerror(VALUE obj, VALUE errn) { int gsl_errno = FIX2INT(errn); return rb_str_new2(gsl_strerror(gsl_errno)); } void Init_gsl_error(VALUE module) { Init_rb_gsl_define_GSL_CONST(module); gsl_set_error_handler(&rb_gsl_error_handler); define_module_functions(module); rb_gsl_define_exceptions(module); }