3
\brief Contains Ruby initialization and some global functions.
8
namespace psi { namespace psirb {
10
// Function declarations
11
bool initialize_ruby();
12
void load_input_file_into_ruby();
13
void process_input_file();
15
VALUE ruby_psi_print_version();
16
VALUE ruby_psi_get_version_major();
17
VALUE ruby_psi_get_version_minor();
18
bool create_ruby_psi_module();
21
extern void print_version();
23
/*! Initializes the Ruby interpreter, sets the Ruby $: and $0 variables,
24
adds the appropriate PSIDATADIR path to Ruby's search path,
25
and also creates the Ruby-ized Psi objects.
26
\return true on success, false on failure
28
bool initialize_ruby()
30
char *psishare_dirname;
32
// Setup and initialize interpreter
35
// Initialize the $: (load path) variable; necessary if the input file loads any other modules
38
// Need to modify the load path of Ruby to include Psi's specific locations
39
// Get the global variable $:
40
VALUE loadpath = rb_gv_get("$:");
41
// pop off the "." directory
42
VALUE popped_value = rb_ary_pop(loadpath);
44
// check to see what we need to add
45
psishare_dirname = getenv("PSIDATADIR");
46
if (psishare_dirname != NULL) {
47
char *tmpstr = (char*)malloc(sizeof(char)*(strlen(psishare_dirname)+6));
48
sprintf(tmpstr, "%s/ruby", psishare_dirname);
49
psishare_dirname = tmpstr;
52
psishare_dirname = strdup(INSTALLEDPSIDATADIR "/ruby");
54
// Convert char* to Ruby string
55
VALUE newpath = rb_str_new2(psishare_dirname);
56
free(psishare_dirname);
58
// push on new location
59
rb_ary_push(loadpath, newpath);
60
// push the "." location back on
61
rb_ary_push(loadpath, popped_value);
63
// Set the name of the Ruby script (and $0) to Psi
66
// Add some basic functionality to Ruby
67
create_ruby_psi_module();
68
Task::create_ruby_class();
69
ZEntry::create_ruby_class();
70
Matrix::create_ruby_class();
76
/*! Loads the Ruby input file into the interpreter. Does not perform syntax checking, nor does
77
it begin executing the code. Just checks to see if the file exists and loads it. */
78
void load_input_file_into_ruby()
81
rb_load_file(Globals::g_szInputFile.c_str());
84
/*! Run the input file. */
85
void process_input_file()
87
// Process the input file
88
// Since I do not want Ruby to take complete control of the system this is a
89
// hack version from Ruby's eval.c file function ruby_eval and ruby_stop
90
// Typically you would call ruby_run but this function does not return at
91
// all from ruby_stop, it invokes an exit function call internally.
95
if (ruby_nerrs > 0) exit(EXIT_FAILURE);
97
if (state && !ex) ex = state;
101
/*! Shutdown the interpreter */
107
//! Ruby function: Psi::Version::print_version
108
/*! Prints out version information from the C-function print_version.
109
\return Qnil, the Ruby equivalent to NULL.
111
VALUE ruby_psi_print_version()
117
//! Ruby function: indent_puts and Psi::indent_puts
118
/*! Increments the number of spaces that will appear at the beginning of a line printed
120
\return Qnil, the Ruby equivalent to NULL.
122
VALUE ruby_psi_indent_puts()
124
Globals::g_iPutsIndent += 2;
128
//! Ruby funcation: unindent_puts and Psi::unindent_puts
129
/*! Decrements the number of spaces that will appear at the beginning of a line printed
131
\return Qnil, the Ruby equivalent to NULL.
133
VALUE ruby_psi_unindent_puts()
135
Globals::g_iPutsIndent -= 2;
136
if (Globals::g_iPutsIndent < 0)
137
Globals::g_iPutsIndent = 0;
141
//! Ruby function: Psi::Version::get_version_major
142
/*! \return The major version value for Psi */
143
VALUE ruby_psi_get_version_major()
145
return INT2FIX(PSI_VERSION_MAJOR);
148
//! Ruby function: Psi::Version::get_version_minor
149
/*! \return The minor version value for Psi */
150
VALUE ruby_psi_get_version_minor()
152
return INT2FIX(PSI_VERSION_MINOR);
155
//! Ruby function: puts
156
/*! This is an override of Ruby's standard puts function. This allows for indentation
157
and redirection of the puts.
158
\param argc Number of Ruby objects to print.
159
\param argv C-array of Ruby objects to print.
160
\return Qnil, the Ruby equvalent to NULL.
162
VALUE ruby_psi_puts(int argc, VALUE *argv)
167
// If we are supposed to be quiet don't print anything
168
if (Globals::g_bQuietRuby == false) {
169
for (i=0; i<Globals::g_iPutsIndent; i++)
170
fprintf(Globals::g_fOutput, " ");
172
for (i=0; i<argc; ++i) {
173
// StringValue calls to_str on the object, if needed, to convert the object to a string.
174
VALUE str = StringValue(argv[i]);
175
// Print the converted objected.
176
fprintf(Globals::g_fOutput, RSTRING(str)->ptr);
178
fprintf(Globals::g_fOutput, "\n");
179
fflush(Globals::g_fOutput);
185
//! Ruby function: Psi::quiet=
186
/*! If quiet=true then puts will not print anything when called */
187
VALUE ruby_psi_quiet_set(VALUE self, VALUE value)
190
Globals::g_bQuietRuby = true;
192
Globals::g_bQuietRuby = false;
197
//! Ruby function: Psi::quiet
198
/*! Returns the quiet value */
199
VALUE ruby_psi_quiet_get(VALUE self, VALUE value)
201
if (Globals::g_bQuietRuby == true)
207
//! Creates a module in the Ruby address space named Psi.
208
/*! All Psi objects/functions reside in this address space. Each function that is to be
209
available to a user in the input file must be registered with Ruby.
210
\returns true on success, false on failure.
212
bool create_ruby_psi_module()
214
// Handle for Version module
217
// Define a Ruby module named Psi
218
Globals::g_rbPsi = rb_define_module("Psi");
220
// Override some commands to ensure output is redirected to where we want
221
// This redefines the global puts function to use our's
222
rb_define_global_function("puts", RUBYCAST(ruby_psi_puts), -1);
223
rb_define_global_function("indent_puts", RUBYCAST(ruby_psi_indent_puts), 0);
224
rb_define_global_function("unindent_puts", RUBYCAST(ruby_psi_unindent_puts), 0);
226
// Define methods that belong to Psi
227
rb_define_module_function(Globals::g_rbPsi, "indent_puts", RUBYCAST(ruby_psi_indent_puts), 0);
228
rb_define_module_function(Globals::g_rbPsi, "unindent_puts", RUBYCAST(ruby_psi_unindent_puts), 0);
229
rb_define_module_function(Globals::g_rbPsi, "quiet=", RUBYCAST(ruby_psi_quiet_set), 1);
230
rb_define_module_function(Globals::g_rbPsi, "quiet", RUBYCAST(ruby_psi_quiet_get), 0);
232
// Define a sub-module of Psi named Version
233
rubyVersion = rb_define_module_under(Globals::g_rbPsi, "Version");
235
// Add methods to the new module: Version
236
rb_define_module_function(rubyVersion, "print_version", RUBYCAST(ruby_psi_print_version), 0);
237
rb_define_module_function(rubyVersion, "get_major", RUBYCAST(ruby_psi_get_version_major), 0);
238
rb_define_module_function(rubyVersion, "get_minor", RUBYCAST(ruby_psi_get_version_minor), 0);
244
}} // namespace psi::psirb