alexandria-zoom 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,94 @@
1
+ Ruby/ZOOM
2
+ =========
3
+
4
+ Ruby/ZOOM provides a Ruby binding to the Z39.50 Object-Orientation Model
5
+ (ZOOM), an abstract object-oriented programming interface to a subset of the
6
+ services specified by the Z39.50 standard, also known as the international
7
+ standard ISO 23950.
8
+
9
+ This software is based (and therefore depends) on YAZ, a free-software
10
+ implementation of the Z39.50/SRW/SRU standards, but could be easily ported to
11
+ any ZOOM compliant implementation.
12
+
13
+ Ruby/ZOOM is free-software, covered by the GNU Lesser General Public License
14
+ and provided without any warranties of any kind.
15
+
16
+ Requirements
17
+ ------------
18
+
19
+ Ruby: http://www.ruby-lang.org/
20
+ YAZ (*): http://www.indexdata.dk/yaz/
21
+
22
+ * : Make sure you did pass the --enabled-shared option to the configure
23
+ script before building YAZ. Ruby/ZOOM requires a YAZ shared library
24
+ and YAZ does not build it by default.
25
+
26
+ Install
27
+ -------
28
+
29
+ 0. gem install alexandria-zoom
30
+
31
+ Build from Source using bundler
32
+ -----------------
33
+
34
+ 0. add to your Gemfile:
35
+ gem "alexandria-zoom"
36
+ 1. bundle
37
+
38
+ Samples
39
+ -------
40
+
41
+ Some programming examples are available in the `sample' directory.
42
+
43
+ Canonical Sample Program
44
+ ------------------------
45
+
46
+ To give a flavour of the Ruby binding, here is ZOOM's equivalent of the
47
+ ``Hello World'' program: a tiny Z39.50 client that fetches and displays
48
+ the MARC record for Farlow & Brett Surman's The Complete Dinosaur from
49
+ the Library of Congress.
50
+
51
+
52
+ require 'zoom'
53
+
54
+ ZOOM::Connection.open('z3950.loc.gov', 7090) do |conn|
55
+ conn.database_name = 'Voyager'
56
+ conn.preferred_record_syntax = 'USMARC'
57
+ rset = conn.search('@attr 1=7 0253333490')
58
+ p rset[0]
59
+ end
60
+
61
+ ZOOM Extended Services
62
+ ----------------------
63
+
64
+ With release 0.4.1 extended services support has been added which allows
65
+ create, update and delete of records. This only works for XML.
66
+ Here's an example adapted from the test suite.
67
+
68
+ require 'zoom'
69
+
70
+ new_record = File.read('programming_ruby.xml')
71
+
72
+ ZOOM::Connection.open('localhost:99999/test') do |conn|
73
+ p = conn.package
74
+ p.wait_action = 'waitIfPossible'
75
+ p.action = 'specialUpdate'
76
+ p.record = new_record
77
+ p.send('update')
78
+ p.send('commit')
79
+ end
80
+
81
+
82
+ Copying
83
+ -------
84
+
85
+ Copyright (c) 2005 Laurent Sansonetti <lrz@chopine.be>
86
+
87
+ This library is free software.
88
+ You can distribute/modify this program under the terms of
89
+ the GNU LESSER GENERAL PUBLIC LICENSE Version 2.1.
90
+
91
+ Project Website
92
+ ---------------
93
+
94
+ http://ruby-zoom.rubyforge.org
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "mkmf"
4
+ require "pkg-config"
5
+
6
+ unless PKGConfig.have_package("yaz")
7
+ warn "yaz development files do not appear to be installed"
8
+ exit(false)
9
+ end
10
+
11
+ unless have_header("yaz/zoom.h")
12
+ warn "yaz zoom header not available"
13
+ exit
14
+ end
15
+
16
+ append_cflags PKGConfig.cflags("yaz")
17
+ append_ldflags PKGConfig.libs("yaz")
18
+
19
+ create_makefile("zoom")
data/ext/zoom/rbzoom.c ADDED
@@ -0,0 +1,34 @@
1
+ /*
2
+ * Copyright (C) 2005 Laurent Sansonetti <lrz@chopine.be>
3
+ *
4
+ * This library is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU Lesser General Public
6
+ * License as published by the Free Software Foundation; either
7
+ * version 2.1 of the License, or (at your option) any later version.
8
+ *
9
+ * This library is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ * Lesser General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU Lesser General Public
15
+ * License along with this library; if not, write to the Free Software
16
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+ */
18
+
19
+ #include "rbzoom.h"
20
+
21
+
22
+ void
23
+ Init_zoom (void)
24
+ {
25
+ VALUE mZoom;
26
+
27
+ mZoom = rb_define_module ("ZOOM");
28
+
29
+ Init_zoom_connection (mZoom);
30
+ Init_zoom_query (mZoom);
31
+ Init_zoom_resultset (mZoom);
32
+ Init_zoom_record (mZoom);
33
+ Init_zoom_package (mZoom);
34
+ }
data/ext/zoom/rbzoom.h ADDED
@@ -0,0 +1,68 @@
1
+ /*
2
+ * Copyright (C) 2005 Laurent Sansonetti <lrz@chopine.be>
3
+ *
4
+ * This library is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU Lesser General Public
6
+ * License as published by the Free Software Foundation; either
7
+ * version 2.1 of the License, or (at your option) any later version.
8
+ *
9
+ * This library is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ * Lesser General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU Lesser General Public
15
+ * License along with this library; if not, write to the Free Software
16
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+ */
18
+
19
+ #ifndef __RBZOOM_H_
20
+ #define __RBZOOM_H_
21
+
22
+ #include <yaz/zoom.h>
23
+ #include <ruby.h>
24
+ #include <assert.h>
25
+
26
+ /* initialization */
27
+ void Init_zoom (void);
28
+ void Init_zoom_connection (VALUE mZoom);
29
+ void Init_zoom_query (VALUE mZoom);
30
+ void Init_zoom_resultset (VALUE mZoom);
31
+ void Init_zoom_record (VALUE mZoom);
32
+ void Init_zoom_package (VALUE mZoom);
33
+
34
+ /* rbzoomoptions.c */
35
+ ZOOM_options ruby_hash_to_zoom_options (VALUE hash);
36
+ VALUE zoom_option_value_to_ruby_value (const char *value);
37
+ void define_zoom_option (VALUE klass, const char *option);
38
+
39
+ /* rbzoomparse.c */
40
+ ZOOM_query rbz_query_get (VALUE obj);
41
+
42
+ /* rbzoomresultset.c */
43
+ VALUE rbz_resultset_make (ZOOM_resultset resultset);
44
+
45
+ /* rbzoomrecord.c */
46
+ VALUE rbz_record_make (ZOOM_record record);
47
+
48
+ /* rbzoompackage.c */
49
+ VALUE rbz_package_make (ZOOM_connection connection, ZOOM_options options);
50
+
51
+ /* rbconnection.c */
52
+ void rbz_connection_check(VALUE obj);
53
+
54
+ /* useful macros */
55
+ #if !defined (RVAL2CSTR)
56
+ # define RVAL2CSTR(x) (NIL_P (x) ? NULL : RSTRING_PTR(x))
57
+ #endif
58
+ #if !defined (CSTR2RVAL)
59
+ # define CSTR2RVAL(x) (x == NULL ? Qnil : rb_str_new2(x))
60
+ #endif
61
+ #if !defined (RVAL2CBOOL)
62
+ # define RVAL2CBOOL(x) (RTEST (x))
63
+ #endif
64
+ #if !defined (CBOOL2RVAL)
65
+ # define CBOOL2RVAL(x) (x ? Qtrue : Qfalse)
66
+ #endif
67
+
68
+ #endif /* __RBZOOM_H_ */
@@ -0,0 +1,346 @@
1
+ /*
2
+ * Copyright (C) 2005 Laurent Sansonetti <lrz@chopine.be>
3
+ *
4
+ * This library is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU Lesser General Public
6
+ * License as published by the Free Software Foundation; either
7
+ * version 2.1 of the License, or (at your option) any later version.
8
+ *
9
+ * This library is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ * Lesser General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU Lesser General Public
15
+ * License along with this library; if not, write to the Free Software
16
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+ */
18
+
19
+ #include "rbzoom.h"
20
+
21
+ #ifdef MAKING_RDOC_HAPPY
22
+ mZoom = rb_define_module("ZOOM");
23
+ #endif
24
+
25
+
26
+ /* Document-class: ZOOM::Connection
27
+ * The Connection object is a session with a target.
28
+ */
29
+ static VALUE cZoomConnection;
30
+
31
+
32
+ static VALUE
33
+ rbz_connection_make (ZOOM_connection connection)
34
+ {
35
+ return connection != NULL
36
+ ? Data_Wrap_Struct (cZoomConnection,
37
+ NULL,
38
+ ZOOM_connection_destroy,
39
+ connection)
40
+ : Qnil;
41
+ }
42
+
43
+ static ZOOM_connection
44
+ rbz_connection_get (VALUE obj)
45
+ {
46
+ ZOOM_connection connection;
47
+
48
+ Data_Get_Struct (obj, struct ZOOM_connection_p, connection);
49
+ assert (connection != NULL);
50
+
51
+ return connection;
52
+ }
53
+
54
+ #define RAISE_IF_FAILED(connection) \
55
+ do { \
56
+ int error; \
57
+ const char *errmsg; \
58
+ const char *addinfo; \
59
+ \
60
+ error = ZOOM_connection_error (connection, \
61
+ &errmsg, \
62
+ &addinfo); \
63
+ if (error != 0) \
64
+ rb_raise (rb_eRuntimeError, "%s (%d) %s", \
65
+ errmsg, error, addinfo); \
66
+ } \
67
+ while (0)
68
+
69
+ void rbz_connection_check(VALUE obj)
70
+ {
71
+ ZOOM_connection connection;
72
+
73
+ connection = rbz_connection_get(obj);
74
+ RAISE_IF_FAILED (connection);
75
+ }
76
+
77
+
78
+ /*
79
+ * call-seq:
80
+ * open(host, port=nil) { |conn| ... }
81
+ *
82
+ * host: hostname of the target to connect to.
83
+ *
84
+ * port: network port of the target to connect to.
85
+ *
86
+ * A convenience method that creates a new connection and attempts to
87
+ * establish a network connection to the given target, basically calling
88
+ * ZOOM::Connection.new and ZOOM::Connection#connect.
89
+ *
90
+ * If a block is given, then it will be called once the connection is
91
+ * established, passing a reference to the connection object as a parameter,
92
+ * and destroying the connection automatically at the end of the block.
93
+ * With no block, this method just returns the connection object.
94
+ *
95
+ * Returns: a newly created ZOOM::Connection object.
96
+ */
97
+ static VALUE
98
+ rbz_connection_open (int argc, VALUE *argv, VALUE self)
99
+ {
100
+ VALUE host;
101
+ VALUE port;
102
+ ZOOM_connection connection;
103
+ VALUE rb_connection;
104
+
105
+ rb_scan_args (argc, argv, "11", &host, &port);
106
+
107
+ connection = ZOOM_connection_new (RVAL2CSTR (host),
108
+ NIL_P (port) ? 0 : FIX2INT (port));
109
+ RAISE_IF_FAILED (connection);
110
+
111
+ rb_connection = rbz_connection_make (connection);
112
+ if (rb_block_given_p ()) {
113
+ rb_yield(rb_connection);
114
+ return Qnil;
115
+ }
116
+ return rb_connection;
117
+ }
118
+
119
+ /*
120
+ * call-seq: new(options=nil)
121
+ *
122
+ * options: options for the connection, as a Hash object.
123
+ *
124
+ * Creates a new connection object, but does not establish a network connection
125
+ * immediately, allowing you to specify options before (if given). You can
126
+ * thus establish the connection using ZOOM::Connection#connect.
127
+ *
128
+ * Returns: a newly created ZOOM::Connection object.
129
+ */
130
+ static VALUE
131
+ rbz_connection_new (int argc, VALUE *argv, VALUE self)
132
+ {
133
+ ZOOM_options options;
134
+ ZOOM_connection connection;
135
+ VALUE rb_options;
136
+
137
+ rb_scan_args (argc, argv, "01", &rb_options);
138
+
139
+ if (NIL_P (rb_options))
140
+ options = ZOOM_options_create ();
141
+ else
142
+ options = ruby_hash_to_zoom_options (rb_options);
143
+
144
+ connection = ZOOM_connection_create (options);
145
+ ZOOM_options_destroy (options);
146
+ RAISE_IF_FAILED (connection);
147
+
148
+ return rbz_connection_make (connection);
149
+ }
150
+
151
+ /*
152
+ * call-seq:
153
+ * connect(host, port=nil)
154
+ *
155
+ * host: hostname of the target to connect to.
156
+ *
157
+ * port: network port of the target to connect to.
158
+ *
159
+ * Establishes a network connection to the target specified by the given
160
+ * arguments. If no port is given, 210 will be used. A colon in the host
161
+ * string denotes the beginning of a port number. If the host string includes
162
+ * a slash, the following part specifies a database for the connection.
163
+ *
164
+ * You can also prefix the host string with a scheme followed by a colon.
165
+ * The default scheme is tcp (Z39.50 protocol). The scheme http selects SRW
166
+ * over HTTP.
167
+ *
168
+ * This method raises an exception on error.
169
+ *
170
+ * Returns: self.
171
+ */
172
+ static VALUE
173
+ rbz_connection_connect (int argc, VALUE *argv, VALUE self)
174
+ {
175
+ ZOOM_connection connection;
176
+ VALUE host;
177
+ VALUE port;
178
+
179
+ rb_scan_args (argc, argv, "11", &host, &port);
180
+
181
+ connection = rbz_connection_get (self);
182
+ ZOOM_connection_connect (connection,
183
+ RVAL2CSTR (host),
184
+ NIL_P (port) ? 0 : FIX2INT (port));
185
+ RAISE_IF_FAILED (connection);
186
+
187
+ return self;
188
+ }
189
+
190
+ /*
191
+ * call-seq:
192
+ * set_option(key, value)
193
+ *
194
+ * key: the name of the option, as a string.
195
+ *
196
+ * value: the value of this option (as a string, integer or boolean).
197
+ *
198
+ * Sets an option on the connection.
199
+ *
200
+ * Returns: self.
201
+ */
202
+ static VALUE
203
+ rbz_connection_set_option (VALUE self, VALUE key, VALUE val)
204
+ {
205
+ ZOOM_connection connection;
206
+
207
+ connection = rbz_connection_get (self);
208
+ ZOOM_connection_option_set (connection,
209
+ RVAL2CSTR (key),
210
+ RVAL2CSTR (rb_obj_as_string (val)));
211
+ RAISE_IF_FAILED (connection);
212
+
213
+ return self;
214
+ }
215
+
216
+ /*
217
+ * call-seq:
218
+ * get_option(key)
219
+ *
220
+ * key: the name of the option, as a string.
221
+ *
222
+ * Gets the value of a connection's option.
223
+ *
224
+ * Returns: the value of the given option, as a string, integer or boolean.
225
+ */
226
+ static VALUE
227
+ rbz_connection_get_option (VALUE self, VALUE key)
228
+ {
229
+ ZOOM_connection connection;
230
+ const char *value;
231
+
232
+ connection = rbz_connection_get (self);
233
+ value = ZOOM_connection_option_get (connection,
234
+ RVAL2CSTR (key));
235
+
236
+ return zoom_option_value_to_ruby_value (value);
237
+ }
238
+
239
+ /*
240
+ * call-seq:
241
+ * search(criterion)
242
+ *
243
+ * criterion: the search criterion, either as a ZOOM::Query object or as a string,
244
+ * representing a PQF query.
245
+ *
246
+ * Searches the connection from the given criterion. You can either create and
247
+ * pass a reference to a ZOOM::Query object, or you can simply pass a string
248
+ * that represents a PQF query.
249
+ *
250
+ * This method raises an exception on error.
251
+ *
252
+ * Returns: a result set from the search, as a ZOOM::ResultSet object,
253
+ * empty if no results were found.
254
+ */
255
+ static VALUE
256
+ rbz_connection_search (VALUE self, VALUE criterion)
257
+ {
258
+ ZOOM_connection connection;
259
+ ZOOM_resultset resultset;
260
+
261
+ connection = rbz_connection_get (self);
262
+ if (TYPE (criterion) == T_STRING)
263
+ resultset = ZOOM_connection_search_pqf (connection,
264
+ RVAL2CSTR (criterion));
265
+ else
266
+ resultset = ZOOM_connection_search (connection,
267
+ rbz_query_get (criterion));
268
+ RAISE_IF_FAILED (connection);
269
+ assert (resultset != NULL);
270
+
271
+ return rbz_resultset_make (resultset);
272
+ }
273
+
274
+
275
+ /*
276
+ * Constructs a new extended services ZOOM::Package using this connections host information.
277
+ *
278
+ * Note: The Perl script passes this connections options if already set, otherwise constructs a new ZOOM::Option object.
279
+ * Currently this method always constructs a new ZOOM::Option object for each package.
280
+ *
281
+ * Returns: a new ZOOM::Package object.
282
+ */
283
+ static VALUE
284
+ rbz_connection_package(VALUE self)
285
+ {
286
+ ZOOM_connection connection;
287
+ ZOOM_options options;
288
+ VALUE package;
289
+
290
+ connection = rbz_connection_get (self);
291
+ options = ZOOM_options_create ();
292
+ package = rbz_package_make(connection, options);
293
+ return package;
294
+ }
295
+
296
+
297
+ void
298
+ Init_zoom_connection (VALUE mZoom)
299
+ {
300
+ VALUE c;
301
+
302
+ c = rb_define_class_under (mZoom, "Connection", rb_cObject);
303
+ rb_undef_alloc_func(c);
304
+
305
+ rb_define_singleton_method (c, "open", rbz_connection_open, -1);
306
+ rb_define_singleton_method (c, "new", rbz_connection_new, -1);
307
+ rb_define_method (c, "connect", rbz_connection_connect, -1);
308
+ rb_define_method (c, "set_option", rbz_connection_set_option, 2);
309
+ rb_define_method (c, "get_option", rbz_connection_get_option, 1);
310
+ rb_define_method (c, "package", rbz_connection_package, 0);
311
+
312
+ define_zoom_option (c, "implementationName");
313
+ define_zoom_option (c, "user");
314
+ define_zoom_option (c, "group");
315
+ define_zoom_option (c, "password");
316
+ define_zoom_option (c, "host");
317
+ define_zoom_option (c, "proxy");
318
+ define_zoom_option (c, "async");
319
+ define_zoom_option (c, "maximumRecordSize");
320
+ define_zoom_option (c, "preferredMessageSize");
321
+ define_zoom_option (c, "lang");
322
+ define_zoom_option (c, "charset");
323
+ define_zoom_option (c, "serverImplementationId");
324
+ define_zoom_option (c, "targetImplementationName");
325
+ define_zoom_option (c, "serverImplementationVersion");
326
+ define_zoom_option (c, "databaseName");
327
+ define_zoom_option (c, "piggyback");
328
+ define_zoom_option (c, "smallSetUpperBound");
329
+ define_zoom_option (c, "largeSetLowerBound");
330
+ define_zoom_option (c, "mediumSetPresentNumber");
331
+ define_zoom_option (c, "smallSetElementSetName");
332
+ define_zoom_option (c, "mediumSetElementSetName");
333
+
334
+ /* herited from Zoom::ResultSet */
335
+ define_zoom_option (c, "start");
336
+ define_zoom_option (c, "count");
337
+ define_zoom_option (c, "presentChunk");
338
+ define_zoom_option (c, "elementSetName");
339
+ define_zoom_option (c, "preferredRecordSyntax");
340
+ define_zoom_option (c, "schema");
341
+ define_zoom_option (c, "setname");
342
+
343
+ rb_define_method (c, "search", rbz_connection_search, 1);
344
+
345
+ cZoomConnection = c;
346
+ }
@@ -0,0 +1,121 @@
1
+ /*
2
+ * Copyright (C) 2005 Laurent Sansonetti <lrz@chopine.be>
3
+ *
4
+ * This library is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU Lesser General Public
6
+ * License as published by the Free Software Foundation; either
7
+ * version 2.1 of the License, or (at your option) any later version.
8
+ *
9
+ * This library is distributed in the hope that it will be useful,
10
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
+ * Lesser General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU Lesser General Public
15
+ * License along with this library; if not, write to the Free Software
16
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
+ */
18
+
19
+ #include <ctype.h>
20
+ #include "rbzoom.h"
21
+
22
+ ZOOM_options
23
+ ruby_hash_to_zoom_options (VALUE hash)
24
+ {
25
+ ZOOM_options options;
26
+ VALUE ary;
27
+ VALUE pair;
28
+ VALUE key;
29
+ VALUE value;
30
+ int i;
31
+
32
+ options = ZOOM_options_create ();
33
+
34
+ ary = rb_funcall (hash, rb_intern ("to_a"), 0);
35
+ for (i = 0; i < RARRAY_LEN(ary); i++) {
36
+ pair = RARRAY_PTR(ary)[i];
37
+ key = RARRAY_PTR(pair)[0];
38
+ value = RARRAY_PTR(pair)[1];
39
+
40
+ switch (TYPE (value)) {
41
+ case T_TRUE:
42
+ case T_FALSE:
43
+ ZOOM_options_set_int (options,
44
+ RVAL2CSTR (key),
45
+ RVAL2CBOOL (value) ? 1 : 0);
46
+ break;
47
+
48
+ case T_FIXNUM:
49
+ ZOOM_options_set_int (options,
50
+ RVAL2CSTR (key),
51
+ FIX2INT (value));
52
+ break;
53
+
54
+ case T_STRING:
55
+ ZOOM_options_set (options,
56
+ RVAL2CSTR (key),
57
+ RVAL2CSTR (value));
58
+ break;
59
+
60
+ default:
61
+ rb_raise (rb_eArgError, "Unrecognized type");
62
+ }
63
+ }
64
+
65
+ return options;
66
+ }
67
+
68
+ VALUE
69
+ zoom_option_value_to_ruby_value (const char *value)
70
+ {
71
+ unsigned int i;
72
+
73
+ if (value == NULL)
74
+ return Qnil;
75
+
76
+ for (i = 0; i < strlen (value); i++)
77
+ if (!isdigit (value [i]))
78
+ return CSTR2RVAL (value);
79
+
80
+ return INT2FIX (atoi (value));
81
+ }
82
+
83
+ void
84
+ define_zoom_option (VALUE klass, const char *option)
85
+ {
86
+ char code [1024];
87
+ char rubyname [128];
88
+ char c;
89
+ unsigned int i;
90
+ unsigned int j;
91
+
92
+ /* rubyfy the option name */
93
+ for (i = 0, j = 0; i < strlen (option) && j < sizeof rubyname; i++, j++) {
94
+ c = option [i];
95
+ if (isupper (c)) {
96
+ rubyname [j++] = '_';
97
+ c = tolower (c);
98
+ }
99
+ else if (c == '-')
100
+ {
101
+ c = '_';
102
+ }
103
+ else if (c == '.')
104
+ {
105
+ c = '_';
106
+ }
107
+
108
+ rubyname [j] = c;
109
+ }
110
+ rubyname [j] = '\0';
111
+
112
+ snprintf (code, sizeof code,
113
+ "def %s; get_option(\"%s\"); end\n"
114
+ "def %s=(val); set_option(\"%s\", val); val; end\n"
115
+ "def set_%s(val); set_option(\"%s\", val); end\n",
116
+ rubyname, option,
117
+ rubyname, option,
118
+ rubyname, option);
119
+
120
+ rb_funcall (klass, rb_intern ("module_eval"), 1, CSTR2RVAL (code));
121
+ }