git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@518 626c5289-ae23-0410-ae9c-e8d60b6d4f22
1300 lines
39 KiB
C++
1300 lines
39 KiB
C++
/********************************************************************
|
|
* Ruby module for SWIG
|
|
*
|
|
* $Header$
|
|
*
|
|
* Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
|
|
* Copyright (C) 2000 Information-technology Promotion Agency, Japan
|
|
*
|
|
* Masaki Fukushima
|
|
*
|
|
********************************************************************/
|
|
|
|
static char cvsroot[] = "$Header$";
|
|
|
|
#include "mod11.h"
|
|
#include "ruby.h"
|
|
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
|
|
static char *usage = "\
|
|
Ruby Options\n\
|
|
-module name - Set module name\n\
|
|
-toplevel - Do not define module\n\
|
|
-feature name - Set feature name (used by `require')\n";
|
|
|
|
#define RCLASS(hash, name) (RClass*)(Getattr(hash, name) ? Data(Getattr(hash, name)) : 0)
|
|
#define SET_RCLASS(hash, name, klass) Setattr(hash, name, NewVoid(klass, 0))
|
|
|
|
static String& indent(String& s, char *sp = tab4) {
|
|
sp >> s;
|
|
String rep = sp;
|
|
s.replace("\n", ("\n" >> rep).get());
|
|
return s;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// RUBY::RUBY()
|
|
//
|
|
// Constructor
|
|
// ---------------------------------------------------------------------
|
|
RUBY::RUBY(void) {
|
|
module = 0;
|
|
modvar = 0;
|
|
feature = 0;
|
|
toplevel = 0;
|
|
import_file = 0;
|
|
current = NO_CPP;
|
|
klass = 0;
|
|
classes = NewHash();
|
|
special_methods = NewHash();
|
|
|
|
// Python style special method name.
|
|
// Basic
|
|
Setattr(special_methods, "__repr__", "inspect");
|
|
Setattr(special_methods, "__str__", "to_s");
|
|
Setattr(special_methods, "__cmp__", "<=>");
|
|
Setattr(special_methods, "__hash__", "hash");
|
|
Setattr(special_methods, "__nonzero__", "nonzero?");
|
|
// Callable
|
|
Setattr(special_methods, "__call__", "call");
|
|
// Collection
|
|
Setattr(special_methods, "__len__", "length");
|
|
Setattr(special_methods, "__getitem__", "[]");
|
|
Setattr(special_methods, "__setitem__", "[]=");
|
|
// Numeric
|
|
Setattr(special_methods, "__add__", "+");
|
|
Setattr(special_methods, "__sub__", "-");
|
|
Setattr(special_methods, "__mul__", "*");
|
|
Setattr(special_methods, "__div__", "/");
|
|
Setattr(special_methods, "__mod__", "%");
|
|
Setattr(special_methods, "__divmod__", "divmod");
|
|
Setattr(special_methods, "__pow__", "**");
|
|
Setattr(special_methods, "__lshift__", "<<");
|
|
Setattr(special_methods, "__rshift__", ">>");
|
|
Setattr(special_methods, "__and__", "&");
|
|
Setattr(special_methods, "__xor__", "^");
|
|
Setattr(special_methods, "__or__", "|");
|
|
Setattr(special_methods, "__neg__", "-@");
|
|
Setattr(special_methods, "__pos__", "+@");
|
|
Setattr(special_methods, "__abs__", "abs");
|
|
Setattr(special_methods, "__invert__", "~");
|
|
Setattr(special_methods, "__int__", "to_i");
|
|
Setattr(special_methods, "__float__", "to_f");
|
|
Setattr(special_methods, "__coerce__", "coerce");
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// RUBY::parse_args(int argc, char *argv[])
|
|
//
|
|
// Parse command line options and initializes variables.
|
|
// ---------------------------------------------------------------------
|
|
void RUBY::parse_args(int argc, char *argv[]) {
|
|
// Look for certain command line options
|
|
for (int i = 1; i < argc; i++) {
|
|
if (argv[i]) {
|
|
if (strcmp(argv[i],"-module") == 0) {
|
|
if (argv[i+1]) {
|
|
set_module(argv[i+1],0);
|
|
Swig_mark_arg(i);
|
|
Swig_mark_arg(i+1);
|
|
i++;
|
|
} else {
|
|
Swig_arg_error();
|
|
}
|
|
} else if (strcmp(argv[i],"-feature") == 0) {
|
|
if (argv[i+1]) {
|
|
char *name = argv[i+1];
|
|
feature = new char [strlen(name)+1];
|
|
strcpy(feature, name);
|
|
Swig_mark_arg(i);
|
|
Swig_mark_arg(i+1);
|
|
i++;
|
|
} else {
|
|
Swig_arg_error();
|
|
}
|
|
} else if (strcmp(argv[i],"-toplevel") == 0) {
|
|
toplevel = 1;
|
|
Swig_mark_arg(i);
|
|
} else if (strcmp(argv[i],"-help") == 0) {
|
|
fprintf(stderr,"%s\n", usage);
|
|
}
|
|
}
|
|
}
|
|
// Check consistency
|
|
if (module && toplevel)
|
|
Swig_arg_error();
|
|
|
|
// Set location of SWIG library
|
|
strcpy(LibDir,"ruby");
|
|
|
|
// Add a symbol to the parser for conditional compilation
|
|
Preprocessor_define((void *) "SWIGRUBY", 0);
|
|
|
|
// Add typemap definitions
|
|
typemap_lang = "ruby";
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// RUBY::parse()
|
|
//
|
|
// Start parsing an interface file.
|
|
// ---------------------------------------------------------------------
|
|
void RUBY::parse() {
|
|
printf("Generating wrappers for Ruby\n");
|
|
headers();
|
|
|
|
// typedef void *VALUE
|
|
DataType value;
|
|
strcpy(value.name, "void");
|
|
value.type = T_VOID;
|
|
value.is_pointer = 1;
|
|
value.implicit_ptr = 0;
|
|
value.typedef_add("VALUE");
|
|
|
|
yyparse(); // Run the SWIG parser
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// RUBY::set_module(char *mod_name,char **mod_list)
|
|
//
|
|
// Sets the module name. Does nothing if it's already set (so it can
|
|
// be overridden as a command line option).
|
|
//
|
|
// mod_list is a NULL-terminated list of additional modules. This
|
|
// is really only useful when building static executables.
|
|
//----------------------------------------------------------------------
|
|
|
|
void RUBY::set_module(char *mod_name, char **mod_list) {
|
|
if (import_file) {
|
|
fprintf(f_init, "%srb_f_require(Qnil, rb_str_new2(\"%s\"));\n", tab4, mod_name);
|
|
delete [] import_file;
|
|
import_file = 0;
|
|
}
|
|
|
|
if (module) return;
|
|
|
|
if (!feature) {
|
|
feature = new char[strlen(mod_name)+1];
|
|
strcpy(feature, mod_name);
|
|
}
|
|
|
|
module = new char[strlen(mod_name)+1];
|
|
strcpy(module, mod_name);
|
|
// module name must be a constant.
|
|
module[0] = toupper(module[0]);
|
|
|
|
modvar = new char[1+strlen(module)+1];
|
|
modvar[0] = 'm';
|
|
strcpy(modvar+1, module);
|
|
|
|
if (mod_list) {
|
|
other_extern << "#ifdef __cplusplus\n"
|
|
<< "extern \"C\" {\n"
|
|
<< "#endif\n";
|
|
for (int i = 0; mod_list[i] != NULL; i++) {
|
|
other_extern << "extern void Init_" << mod_list[i] << "(void);\n";
|
|
other_init << tab4 << "Init_" << mod_list[i] << "();\n";
|
|
}
|
|
other_extern << "#ifdef __cplusplus\n"
|
|
<< "}\n"
|
|
<< "#endif\n";
|
|
}
|
|
}
|
|
|
|
|
|
static void insert_file(char *filename, FILE *file) {
|
|
if (Swig_insert_file(filename, file) == -1) {
|
|
fprintf(stderr,
|
|
"SWIG : Fatal error. "
|
|
"Unable to locate %s. (Possible installation problem).\n",
|
|
filename);
|
|
SWIG_exit(1);
|
|
}
|
|
}
|
|
// ----------------------------------------------------------------------
|
|
// RUBY::headers(void)
|
|
//
|
|
// Generate the appropriate header files for RUBY interface.
|
|
// ----------------------------------------------------------------------
|
|
void RUBY::headers(void) {
|
|
Swig_banner(f_header);
|
|
fprintf(f_header,"/* Implementation : RUBY */\n\n");
|
|
fprintf(f_header,"#define SWIGRUBY\n");
|
|
|
|
insert_file("ruby.swg", f_header);
|
|
if (NoInclude) {
|
|
insert_file("rubydec.swg", f_header);
|
|
} else {
|
|
insert_file("rubydef.swg", f_header);
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// RUBY::initialize(void)
|
|
//
|
|
// Produces an initialization function. Assumes that the module
|
|
// name has already been specified.
|
|
// ---------------------------------------------------------------------
|
|
void RUBY::initialize() {
|
|
if (!module) {
|
|
fprintf(stderr,"SWIG : *** Warning. No module name specified.\n");
|
|
set_module("swig", NULL); // Pick a default name
|
|
}
|
|
|
|
fprintf(f_header,"#define SWIG_init Init_%s\n", feature);
|
|
fprintf(f_header,"#define SWIG_name \"%s\"\n\n", module);
|
|
if (!toplevel) fprintf(f_header,"static VALUE %s;\n", modvar);
|
|
fprintf(f_header,"\n%s\n", (char *)other_extern.get());
|
|
|
|
// Start generating the initialization function
|
|
String s;
|
|
s << "\n"
|
|
<< "#ifdef __cplusplus\n"
|
|
<< "extern \"C\"\n"
|
|
<<"#endif\n"
|
|
<< "void Init_" << feature << "(void) {\n"
|
|
<< other_init;
|
|
if (!toplevel) {
|
|
s << tab4 << modvar << " = rb_define_module(\"" << module << "\");\n";
|
|
}
|
|
s << "\n";
|
|
fprintf(f_init, s.get());
|
|
klass = new RClass();
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// RUBY::close(void)
|
|
//
|
|
// Finish the initialization function. Close any additional files and
|
|
// resources in use.
|
|
// ---------------------------------------------------------------------
|
|
void RUBY::close(void) {
|
|
// Finish off our init function
|
|
fprintf(f_init, "\n");
|
|
emit_ptr_equivalence(f_init);
|
|
fprintf(f_init,"}\n");
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// RUBY::make_wrapper_name(char *cname)
|
|
//
|
|
// Creates a name for a wrapper function
|
|
// cname = Name of the C function
|
|
// ---------------------------------------------------------------------
|
|
char *RUBY::make_wrapper_name(char *cname) {
|
|
return Swig_name_wrapper(cname);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// RUBY::create_command(char *cname, char *iname)
|
|
//
|
|
// Creates a new command from a C function.
|
|
// cname = Name of the C function
|
|
// iname = Name of function in scripting language
|
|
// argc = Number of arguments
|
|
// ---------------------------------------------------------------------
|
|
void RUBY::create_command(char *cname, char *iname, int argc) {
|
|
String wname = make_wrapper_name(cname);
|
|
if (CPlusPlus) {
|
|
"VALUEFUNC(" >> wname << ")";
|
|
}
|
|
if (current != NO_CPP)
|
|
iname = klass->strip(iname);
|
|
if (Getattr(special_methods, iname)) {
|
|
iname = GetChar(special_methods, iname);
|
|
}
|
|
|
|
String s, temp;
|
|
switch (current) {
|
|
case MEMBER_FUNC:
|
|
klass->init << tab4 << "rb_define_method(" << klass->vname << ", \""
|
|
<< iname << "\", " << wname << ", " << argc << ");\n";
|
|
break;
|
|
case CONSTRUCTOR:
|
|
s << tab4 << "rb_define_singleton_method(" << klass->vname
|
|
<< ", \"new\", " << wname << ", " << argc << ");\n";
|
|
klass->init.replace("$constructor", s.get());
|
|
break;
|
|
case MEMBER_VAR:
|
|
temp = iname;
|
|
temp.replace("_set", "=");
|
|
temp.replace("_get", "");
|
|
klass->init << tab4 << "rb_define_method(" << klass->vname << ", \""
|
|
<< temp << "\", " << wname << ", " << argc << ");\n";
|
|
break;
|
|
case STATIC_FUNC:
|
|
klass->init << tab4 << "rb_define_singleton_method(" << klass->vname
|
|
<< ", \"" << iname << "\", " << wname << ", " << argc
|
|
<< ");\n";
|
|
break;
|
|
default:
|
|
if (toplevel) {
|
|
s << tab4 << "rb_define_global_function(\""
|
|
<< iname << "\", " << wname << ", " << argc << ");\n";
|
|
} else {
|
|
s << tab4 << "rb_define_module_function(" << modvar << ", \""
|
|
<< iname << "\", " << wname << ", " << argc << ");\n";
|
|
}
|
|
fprintf(f_init, s.get());
|
|
break;
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// RUBY::create_function(char *name, char *iname, DataType *d, ParmList *l)
|
|
//
|
|
// Create a function declaration and register it with the interpreter.
|
|
// name = Name of real C function
|
|
// iname = Name of function in scripting language
|
|
// t = Return datatype
|
|
// l = Function parameters
|
|
// ---------------------------------------------------------------------
|
|
void RUBY::create_function(char *name, char *iname, DataType *t, ParmList *l) {
|
|
String source, target;
|
|
char *tm;
|
|
String cleanup, outarg;
|
|
WrapperFunction f;
|
|
|
|
// Ruby needs no destructor wrapper
|
|
if (current == DESTRUCTOR)
|
|
return;
|
|
|
|
char *wname = make_wrapper_name(name);
|
|
String mname, inamebuf;
|
|
int predicate = 0;
|
|
switch (current) {
|
|
case MEMBER_FUNC:
|
|
case MEMBER_VAR:
|
|
case STATIC_FUNC:
|
|
mname = klass->strip(iname);
|
|
if (Getattr(klass->predmethods, mname.get())) {
|
|
predicate = 1;
|
|
inamebuf = iname;
|
|
inamebuf << "?";
|
|
iname = inamebuf.get();
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Get number of arguments
|
|
int numarg = l->numarg();
|
|
int numopt = l->numopt();
|
|
int numignore = l->nparms - numarg;
|
|
int start = 0;
|
|
int use_self = 0;
|
|
switch (current) {
|
|
case MEMBER_FUNC:
|
|
case MEMBER_VAR:
|
|
numarg--;
|
|
start++;
|
|
use_self = 1;
|
|
break;
|
|
}
|
|
|
|
int numreq = 0;
|
|
int numoptreal = 0;
|
|
for (int i = start; i < l->nparms; i++) {
|
|
if (!l->get(i)->ignore) {
|
|
if (i >= l->nparms - numopt) numoptreal++;
|
|
else numreq++;
|
|
}
|
|
}
|
|
int vararg = (numoptreal != 0);
|
|
|
|
// Now write the wrapper function itself
|
|
f.def << "static VALUE\n" << wname << "(";
|
|
if (vararg) {
|
|
f.def << "int argc, VALUE *argv, VALUE self";
|
|
} else {
|
|
f.def << "VALUE self";
|
|
for (int i = start; i < l->nparms; i++) {
|
|
if (!l->get(i)->ignore) {
|
|
f.def << ", VALUE varg" << i;
|
|
}
|
|
}
|
|
}
|
|
f.def << ") {";
|
|
|
|
// Emit all of the local variables for holding arguments.
|
|
if (vararg) {
|
|
for (int i = start; i < l->nparms; i++) {
|
|
if (!l->get(i)->ignore) {
|
|
String s;
|
|
s << "varg" << i;
|
|
f.add_local("VALUE", s.get());
|
|
}
|
|
}
|
|
}
|
|
f.add_local("VALUE", "vresult", "Qnil");
|
|
int pcount = emit_args(t,l,f);
|
|
|
|
#if 0
|
|
String temp;
|
|
temp << "/* " << name << " */" << br;
|
|
temp << "/* nparms = " << l->nparms << " */" << br;
|
|
temp << "/* numarg = " << numarg << " */" << br;
|
|
temp << "/* numopt = " << numopt << " */" << br;
|
|
temp << "/* numignore = " << numignore << " */" << br;
|
|
temp << "/* numoptreal = " << numoptreal << " */" << br;
|
|
temp << "/* pcount = " << pcount << " */" << br;
|
|
temp << "/* rb_scan_args(argc, argv, \""
|
|
<< (numarg-numoptreal) << numoptreal << "\") */" << br;
|
|
temp << br;
|
|
if (numignore != 0) fprintf(stderr, temp);
|
|
f.code << temp;
|
|
#endif
|
|
// Emit count to check the number of arguments
|
|
if (vararg) {
|
|
f.code << tab4 << "rb_scan_args(argc, argv, \""
|
|
<< (numarg-numoptreal) << numoptreal << "\"";
|
|
for (int i = start; i < l->nparms; i++) {
|
|
if (!l->get(i)->ignore) {
|
|
f.code << ", &varg" << i;
|
|
}
|
|
}
|
|
f.code << ");\n";
|
|
}
|
|
|
|
// Now walk the function parameter list and generate code
|
|
// to get arguments
|
|
int j = 0; // Total number of non-optional arguments
|
|
|
|
for (int i = 0; i < pcount ; i++) {
|
|
Parm &p = (*l)[i]; // Get the ith argument
|
|
source = "";
|
|
target = "";
|
|
|
|
// Produce string representation of source and target arguments
|
|
int selfp = (use_self && i == 0);
|
|
if (selfp)
|
|
source << "self";
|
|
else
|
|
source << "varg" << i;
|
|
target << "_arg" << i;
|
|
|
|
if (!p.ignore) {
|
|
char *tab = tab4;
|
|
if (j >= (pcount-numopt)) { // Check if parsing an optional argument
|
|
f.code << tab4 << "if (argc > " << j - start << ") {\n";
|
|
tab = tab8;
|
|
}
|
|
|
|
// Get typemap for this argument
|
|
tm = ruby_typemap_lookup("in",p.t,p.name,source.get(),target.get(),&f);
|
|
if (tm) {
|
|
String s = tm;
|
|
f.code << indent(s, tab) << "\n";
|
|
f.code.replace("$arg",source.get()); // Perform a variable replacement
|
|
} else {
|
|
fprintf(stderr,"%s : Line %d. No typemapping for datatype %s\n",
|
|
input_file,line_number, p.t->print_type());
|
|
}
|
|
if (j >= (pcount-numopt))
|
|
f.code << tab4 << "} \n";
|
|
j++;
|
|
}
|
|
|
|
// Check to see if there was any sort of a constaint typemap
|
|
tm = ruby_typemap_lookup("check",p.t,p.name,source.get(),target.get());
|
|
if (tm) {
|
|
String s = tm;
|
|
f.code << indent(s) << "\n";
|
|
f.code.replace("$arg",source.get());
|
|
}
|
|
|
|
// Check if there was any cleanup code (save it for later)
|
|
tm = ruby_typemap_lookup("freearg",p.t,p.name,target.get(),source.get());
|
|
if (tm) {
|
|
String s = tm;
|
|
cleanup << indent(s) << "\n";
|
|
cleanup.replace("$arg",source.get());
|
|
}
|
|
|
|
tm = ruby_typemap_lookup("argout",p.t,p.name,target.get(),"vresult");
|
|
if (tm) {
|
|
String s = tm;
|
|
outarg << indent(s) << "\n";
|
|
outarg.replace("$arg",source.get());
|
|
}
|
|
}
|
|
|
|
// Now write code to make the function call
|
|
emit_func_call(name,t,l,f);
|
|
|
|
// Return value if necessary
|
|
if ((t->type != T_VOID) || (t->is_pointer)) {
|
|
if (predicate) {
|
|
f.code << tab4 << "vresult = (_result ? Qtrue : Qfalse);\n";
|
|
} else {
|
|
tm = ruby_typemap_lookup("out",t,name,"_result","vresult");
|
|
if (tm) {
|
|
String s = tm;
|
|
f.code << indent(s) << "\n";
|
|
} else {
|
|
fprintf(stderr,"%s : Line %d. No return typemap for datatype %s\n",
|
|
input_file,line_number,t->print_type());
|
|
}
|
|
}
|
|
}
|
|
|
|
// Dump argument output code;
|
|
f.code << outarg;
|
|
|
|
// Dump the argument cleanup code
|
|
f.code << cleanup;
|
|
|
|
// Look for any remaining cleanup. This processes the %new directive
|
|
if (NewObject) {
|
|
tm = ruby_typemap_lookup("newfree",t,name,"_result","");
|
|
if (tm) {
|
|
String s = tm;
|
|
f.code << indent(s) << "\n";
|
|
}
|
|
}
|
|
|
|
// free pragma
|
|
if (current == MEMBER_FUNC && Getattr(klass->freemethods, mname.get())) {
|
|
f.code << tab4 << "DATA_PTR(self) = 0;\n";
|
|
}
|
|
|
|
// Special processing on return value.
|
|
tm = ruby_typemap_lookup("ret",t,name,"_result","");
|
|
if (tm) {
|
|
String s = tm;
|
|
f.code << indent(s) << "\n";
|
|
}
|
|
|
|
// Wrap things up (in a manner of speaking)
|
|
f.code << tab4 << "return vresult;\n}\n";
|
|
|
|
// Substitute the cleanup code
|
|
f.code.replace("$cleanup",cleanup.get());
|
|
|
|
// Emit the function
|
|
f.print(f_wrappers);
|
|
|
|
// Now register the function with the language
|
|
create_command(name, iname, (vararg ? -1 : numarg));
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
|
// RUBY::link_variable(char *name, char *iname, DataType *t)
|
|
//
|
|
// Create a link to a C variable.
|
|
// name = Name of C variable
|
|
// iname = Name of variable in scripting language
|
|
// t = Datatype of the variable
|
|
// ---------------------------------------------------------------------
|
|
void RUBY::link_variable(char *name, char *iname, DataType *t) {
|
|
char *tm;
|
|
String getfname, setfname;
|
|
WrapperFunction getf, setf;
|
|
int mod_attr = 0;
|
|
|
|
// module attribute?
|
|
if (current == STATIC_VAR || !toplevel)
|
|
mod_attr = 1;
|
|
|
|
// create getter
|
|
getfname = Swig_name_get(name);
|
|
getfname.replace("::", "_"); /* FIXME: Swig_name_get bug? */
|
|
getf.def << "static VALUE\n" << getfname << "(";
|
|
if (mod_attr) getf.def << "VALUE self";
|
|
getf.def << ") {";
|
|
getf.add_local("VALUE", "_val");
|
|
tm = ruby_typemap_lookup("varout",t,name,name,"_val");
|
|
if (!tm)
|
|
tm = ruby_typemap_lookup("out",t,name,name,"_val");
|
|
if (tm) {
|
|
String s = tm;
|
|
getf.code << indent(s) << "\n";
|
|
} else if (!t->is_pointer && t->type == T_USER) {
|
|
// Hack this into a pointer
|
|
t->is_pointer++;
|
|
t->remember();
|
|
getf.code << tab4 << "_val = SWIG_NewPointerObj((void *)&" << name
|
|
<< ", \"" << t->print_mangle() << "\");\n";
|
|
t->is_pointer--;
|
|
} else {
|
|
fprintf(stderr,"%s: Line %d. Unable to link with variable type %s\n",
|
|
input_file,line_number,t->print_type());
|
|
}
|
|
getf.code << tab4 << "return _val;\n}\n";
|
|
getf.print(f_wrappers);
|
|
|
|
if (Status & STAT_READONLY) {
|
|
setfname = "NULL";
|
|
} else {
|
|
// create setter
|
|
setfname = Swig_name_set(name);
|
|
setfname.replace("::", "_"); /* FIXME: Swig_name_get bug? */
|
|
if (mod_attr)
|
|
setf.def << "static VALUE\n" << setfname << "(VALUE self, ";
|
|
else
|
|
setf.def << "static void\n" << setfname << "(";
|
|
setf.def << "VALUE _val) {";
|
|
tm = ruby_typemap_lookup("varin",t,name,"_val",name);
|
|
if (!tm)
|
|
tm = ruby_typemap_lookup("in",t,name,"_val",name);
|
|
if (tm) {
|
|
String s = tm;
|
|
setf.code << indent(s) << "\n";
|
|
} else if (!t->is_pointer && t->type == T_USER) {
|
|
t->is_pointer++;
|
|
setf.add_local(t->print_type(), "temp");
|
|
setf.code << tab4 << "temp = (" << t->print_type() << ")"
|
|
<< "SWIG_ConvertPtr(_val, \"" << t->print_mangle() << "\");\n";
|
|
setf.code << tab4 << name << " = *temp;\n";
|
|
t->is_pointer--;
|
|
} else {
|
|
fprintf(stderr,"%s: Line %d. Unable to link with variable type %s\n",
|
|
input_file,line_number,t->print_type());
|
|
}
|
|
if (mod_attr)
|
|
setf.code << tab4 << "return _val;\n";
|
|
setf.code << "}\n";
|
|
setf.print(f_wrappers);
|
|
}
|
|
|
|
// define accessor method
|
|
if (CPlusPlus) {
|
|
"VALUEFUNC(" >> getfname << ")";
|
|
"VALUEFUNC(" >> setfname << ")";
|
|
}
|
|
|
|
String s;
|
|
switch (current) {
|
|
case STATIC_VAR:
|
|
// C++ class variable
|
|
s << tab4 << "rb_define_singleton_method(" << klass->vname << ", \""
|
|
<< klass->strip(iname) << "\", " << getfname << ", 0);\n";
|
|
if (!(Status & STAT_READONLY)) {
|
|
s << tab4 << "rb_define_singleton_method(" << klass->vname << ", \""
|
|
<< klass->strip(iname) << "=\", " << setfname << ", 1);\n";
|
|
}
|
|
klass->init << s;
|
|
break;
|
|
default:
|
|
// C global variable
|
|
if (toplevel) {
|
|
// wrapped in Ruby global variable
|
|
s << tab4 << "rb_define_virtual_variable(\"" << iname << "\", "
|
|
<< getfname << ", " << setfname << ");\n";
|
|
} else {
|
|
// wrapped in Ruby module attribute
|
|
s << tab4 << "rb_define_singleton_method(" << modvar << ", \""
|
|
<< iname << "\", " << getfname << ", 0);\n";
|
|
if (!(Status & STAT_READONLY)) {
|
|
s << tab4 << "rb_define_singleton_method(" << modvar << ", \""
|
|
<< iname << "=\", " << setfname << ", 1);\n";
|
|
}
|
|
}
|
|
fputs(s.get(), f_init);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
// ---------------------------------------------------------------------
|
|
// RUBY::validate_const_name(char *name)
|
|
//
|
|
// Validate constant name.
|
|
// ---------------------------------------------------------------------
|
|
char *RUBY::validate_const_name(char *name) {
|
|
if (!name || name[0] == '\0')
|
|
return name;
|
|
|
|
if (isupper(name[0]))
|
|
return name;
|
|
|
|
if (islower(name[0])) {
|
|
name[0] = toupper(name[0]);
|
|
fprintf(stderr,"%s : Line %d. Wrong constant/class/module name "
|
|
"(corrected to `%s')\n", input_file, line_number, name);
|
|
return name;
|
|
}
|
|
|
|
fprintf(stderr,"%s : Line %d. Wrong constant/class/module name\n",
|
|
input_file, line_number);
|
|
return name;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// RUBY::declare_const(char *name, char *iname, DataType *type, char *value)
|
|
//
|
|
// Makes a constant.
|
|
// name = Name of the constant
|
|
// iname = Scripting language name of constant
|
|
// type = Datatype of the constant
|
|
// value = Constant value (as a string)
|
|
// ---------------------------------------------------------------------
|
|
void RUBY::declare_const(char *name, char *iname, DataType *type, char *value) {
|
|
char *tm;
|
|
|
|
if (current == CLASS_CONST)
|
|
iname = klass->strip(iname);
|
|
|
|
tm = ruby_typemap_lookup("const",type,name,value,iname);
|
|
if (tm) {
|
|
String str = tm;
|
|
str.replace("$value",value);
|
|
if (current == CLASS_CONST) {
|
|
str.replace("$module", klass->vname.get());
|
|
indent(str);
|
|
klass->init << str << "\n";
|
|
} else {
|
|
if (toplevel)
|
|
str.replace("$module", "rb_cObject");
|
|
else
|
|
str.replace("$module", modvar);
|
|
indent(str);
|
|
fprintf(f_init,"%s\n", str.get());
|
|
}
|
|
} else {
|
|
fprintf(stderr,"%s : Line %d. Unable to create constant %s = %s\n",
|
|
input_file, line_number, type->print_type(), value);
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// RUBY::ruby_typemap_lookup(char *op, DataType *type, char *pname, char *source, char *target, WrapperFunction *f = 0)
|
|
//
|
|
// Ruby specific typemap_lookup.
|
|
// op = string code for type of mapping
|
|
// type = the datatype
|
|
// pname = an optional parameter name
|
|
// source = a string with the source variable
|
|
// target = a string containing the target value
|
|
// f = a wrapper function object (optional)
|
|
// ---------------------------------------------------------------------
|
|
char *RUBY::ruby_typemap_lookup(char *op, DataType *type, char *pname, char *source, char *target, WrapperFunction *f = 0) {
|
|
static String s;
|
|
char *tm;
|
|
String target_replace = target;
|
|
target = target_replace.get();
|
|
|
|
RClass *cls = RCLASS(classes, type->name);
|
|
s = "";
|
|
|
|
if ((strcmp("out", op) == 0 || strcmp("in", op) == 0)
|
|
&& strcmp(type->name, "VALUE") == 0) {
|
|
s << "$target = $source;";
|
|
} else if (strcmp("out", op) == 0 && type->type == T_USER &&
|
|
type->is_pointer == 1 && cls) {
|
|
const char *vname = (current == CONSTRUCTOR ? "self" : cls->vname.get());
|
|
s << "$target = Wrap_" << cls->cname << "(" << vname << ", $source);";
|
|
} else if (strcmp("in", op)==0 && type->type == T_USER &&
|
|
type->is_pointer == 1 && cls) {
|
|
s << "Get_" << cls->cname << "($source, $target);";
|
|
} else {
|
|
tm = typemap_lookup(op, typemap_lang, type, pname, source, target, f);
|
|
if (tm) {
|
|
return tm;
|
|
}
|
|
|
|
s = "";
|
|
if (strcmp("in", op) == 0) {
|
|
String v;
|
|
if (from_VALUE(type, "$source", v))
|
|
s << "$target = " << v << ";";
|
|
} else if (strcmp("out", op) == 0) {
|
|
String v;
|
|
if (to_VALUE(type, "$source", v))
|
|
s << "$target = " << v << ";";
|
|
} else if (strcmp("const", op) == 0) {
|
|
String v;
|
|
if (to_VALUE(type, "$value", v, 1)) {
|
|
s << "rb_define_const($module, \"$target\", " << v << ");";
|
|
validate_const_name(target);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (strlen(s.get()) == 0) {
|
|
return NULL;
|
|
}
|
|
|
|
if (source && strlen(source) > 0)
|
|
s.replace("$source", source);
|
|
if (target && strlen(target) > 0)
|
|
s.replace("$target", target);
|
|
s.replace("$type", type->print_type());
|
|
return s.get();
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// RUBY::to_VALUE(DataType *type, char *value, literal)
|
|
//
|
|
// Makes a VALUE (as a string)
|
|
// type = Datatype of the C value
|
|
// value = C value (as a string)
|
|
// str = resulting code (as a string)
|
|
// raw = value is raw string (not quoted) ?
|
|
// ---------------------------------------------------------------------
|
|
int RUBY::to_VALUE(DataType *type, char *value, String& str, int raw = 0) {
|
|
str = "";
|
|
if (type->is_pointer == 0) {
|
|
switch(type->type) {
|
|
case T_INT:case T_SINT:
|
|
case T_SHORT: case T_SSHORT:
|
|
case T_LONG: case T_SLONG:
|
|
case T_SCHAR:
|
|
str << "INT2NUM(" << value << ")";
|
|
break;
|
|
case T_UINT:
|
|
case T_USHORT:
|
|
case T_ULONG:
|
|
case T_UCHAR:
|
|
str << "UINT2NUM(" << value << ")";
|
|
break;
|
|
case T_DOUBLE:
|
|
case T_FLOAT:
|
|
str << "rb_float_new(" << value << ")";
|
|
break;
|
|
case T_CHAR:
|
|
str << "rb_str_new(&" << value << ", 1)";
|
|
break;
|
|
case T_BOOL:
|
|
str << "(" << value << " ? Qtrue : Qfalse)";
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
} else if ((type->type == T_CHAR) && (type->is_pointer == 1)) {
|
|
if (raw)
|
|
str << "rb_str_new2(\"" << value << "\")";
|
|
else
|
|
str << "rb_str_new2(" << value << ")";
|
|
} else {
|
|
str << "SWIG_NewPointerObj((void *)" << value << ", \"" << type->print_mangle() << "\")";
|
|
}
|
|
|
|
if (strlen(str.get()) == 0)
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// RUBY::from_VALUE(DataType *type, char *value)
|
|
//
|
|
// extract VALUE
|
|
// type = Datatype of the C value
|
|
// value = Ruby VALUE (as a string)
|
|
// str = resulting code (as a string)
|
|
// ---------------------------------------------------------------------
|
|
int RUBY::from_VALUE(DataType *type, char *value, String& str) {
|
|
str = "";
|
|
if (type->is_pointer == 0) {
|
|
switch(type->type) {
|
|
case T_INT:case T_SINT:
|
|
str << "NUM2INT(" << value << ")";
|
|
break;
|
|
case T_LONG: case T_SLONG:
|
|
str << "NUM2LONG(" << value << ")";
|
|
break;
|
|
case T_SHORT: case T_SSHORT:
|
|
str << "NUM2SHRT(" << value << ")";
|
|
break;
|
|
case T_UINT:
|
|
str << "NUM2UINT(" << value << ")";
|
|
break;
|
|
case T_ULONG:
|
|
str << "NUM2ULONG(" << value << ")";
|
|
break;
|
|
case T_USHORT:
|
|
str << "NUM2USHRT(" << value << ")";
|
|
break;
|
|
case T_DOUBLE:
|
|
case T_FLOAT:
|
|
str << "NUM2DBL(" << value << ")";
|
|
break;
|
|
case T_CHAR: case T_SCHAR: case T_UCHAR:
|
|
str << "NUM2CHR(" << value << ")";
|
|
break;
|
|
case T_BOOL:
|
|
str << "RTEST(" << value << ")";
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
} else if ((type->type == T_CHAR) && (type->is_pointer == 1)) {
|
|
str << "STR2CSTR(" << value << ")";
|
|
} else {
|
|
str << "SWIG_ConvertPtr(" << value << ", \"" << type->print_mangle() << "\")";
|
|
}
|
|
|
|
if (strlen(str.get()) == 0)
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
// void RUBY::cpp_open_class(char *classname, char *classrename, char *ctype, int strip)
|
|
//
|
|
// Open a new C++ class.
|
|
//
|
|
// INPUTS:
|
|
// name = Real name of the C++ class
|
|
// rename = New name of the class (if %name was used)
|
|
// ctype = Class type (struct, class, union, etc...)
|
|
// strip = Flag indicating whether we should strip the
|
|
// class type off
|
|
//
|
|
// This function is in charge of creating a new class. The SWIG parser has
|
|
// already processed the entire class definition prior to calling this
|
|
// function (which should simplify things considerably).
|
|
//
|
|
// ----------------------------------------------------------------------
|
|
void RUBY::cpp_open_class(char *cname, char *rename, char *ctype, int strip) {
|
|
this->Language::cpp_open_class(cname, rename, ctype, strip);
|
|
|
|
klass = RCLASS(classes, cname);
|
|
|
|
if (strip) {
|
|
klass->type = "";
|
|
klass->type << klass->cname;
|
|
} else {
|
|
klass->type = "";
|
|
klass->type << ctype << " " << klass->cname;
|
|
}
|
|
|
|
klass->header << "\nVALUE " << klass->vname << ";\n";
|
|
klass->init << "\n" << tab4;
|
|
if (toplevel) {
|
|
klass->init << klass->vname << " = rb_define_class("
|
|
<< "\"" << klass->name << "\", $super);\n";
|
|
} else {
|
|
klass->init << klass->vname << " = rb_define_class_under(" << modvar
|
|
<< ", \"" << klass->name << "\", $super);\n";
|
|
}
|
|
klass->includes.replace("$class", klass->vname.get());
|
|
klass->init << klass->includes;
|
|
klass->init << "$constructor";
|
|
|
|
klass->header
|
|
<< "$markproto"
|
|
<< "$freeproto"
|
|
<< "#define Wrap_" << klass->cname << "(klass, ptr) (\\\n"
|
|
<< tab4 << "(ptr) ? Data_Wrap_Struct(klass"
|
|
<< ", $markfunc, $freefunc, ptr) : Qnil )\n"
|
|
<< "#define Get_" << klass->cname << "(val, ptr) {\\\n"
|
|
<< tab4 << "if (NIL_P(val)) ptr = NULL;\\\n"
|
|
<< tab4 << "else {\\\n"
|
|
<< tab8 << "if (!rb_obj_is_kind_of(val, " << klass->vname << "))\\\n"
|
|
<< tab8 << tab4 << "rb_raise(rb_eTypeError, \"wrong argument type"
|
|
<< " (expected " << klass->name << ")\");\\\n"
|
|
<< tab8 << "Data_Get_Struct(val, " << klass->type << ", ptr);\\\n"
|
|
<< tab8 << "if (!ptr) rb_raise(rb_eRuntimeError, \""
|
|
<< "This " << klass->name << " already released\");\\\n"
|
|
<< tab4 << "}\\\n"
|
|
<< "}\n";
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// void RUBY::cpp_close_class()
|
|
//
|
|
// Close the current class
|
|
// ---------------------------------------------------------------------
|
|
void RUBY::cpp_close_class() {
|
|
this->Language::cpp_close_class();
|
|
|
|
klass->header.replace("$markfunc", "0");
|
|
klass->header.replace("$markproto", "");
|
|
if (!klass->destructor_defined) {
|
|
klass->header.replace("$freefunc", "0");
|
|
klass->header.replace("$freeproto", "");
|
|
}
|
|
fprintf(f_header, klass->header.get());
|
|
|
|
klass->aliases.replace("$class", klass->vname.get());
|
|
klass->init << klass->aliases;
|
|
|
|
String s;
|
|
s << tab4 << "rb_undef_method(CLASS_OF(" << klass->vname
|
|
<< "), \"new\");\n";
|
|
klass->init.replace("$constructor", s.get());
|
|
klass->init.replace("$super", "rb_cObject");
|
|
|
|
fprintf(f_init, klass->init.get());
|
|
|
|
klass = 0;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
// void RUBY::cpp_inherit(char **baseclass, int mode)
|
|
//
|
|
// Inherit attributes from given baseclass.
|
|
//
|
|
// INPUT:
|
|
// baseclass = NULL terminate list of baseclasses
|
|
//
|
|
// ---------------------------------------------------------------------
|
|
|
|
void RUBY::cpp_inherit(char **baseclass, int mode) {
|
|
if (!baseclass)
|
|
return;
|
|
|
|
for (int i = 0; baseclass[i]; i++) {
|
|
RClass *super = RCLASS(classes, baseclass[i]);
|
|
if (super) {
|
|
klass->init.replace("$super", super->vname.get());
|
|
break; // ignore multiple inheritance
|
|
}
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
// void RUBY::cpp_member_func(char *name, char *iname, DataType *t, ParmList *l)
|
|
//
|
|
// Method for adding C++ member function
|
|
//
|
|
// INPUTS:
|
|
// name - name of the member function
|
|
// iname - renaming (if given)
|
|
// t - Return datatype
|
|
// l - Parameter list
|
|
//
|
|
// By default, we're going to create a function of the form :
|
|
//
|
|
// Foo_bar(this,args)
|
|
//
|
|
// Where Foo is the classname, bar is the member name and the this pointer
|
|
// is explicitly attached to the beginning.
|
|
//
|
|
// The renaming only applies to the member function part, not the full
|
|
// classname.
|
|
//
|
|
// ---------------------------------------------------------------------
|
|
void RUBY::cpp_member_func(char *name, char *iname, DataType *t, ParmList *l) {
|
|
current = MEMBER_FUNC;
|
|
this->Language::cpp_member_func(name, iname, t, l);
|
|
current = NO_CPP;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// void RUBY::cpp_constructor(char *name, char *iname, ParmList *l)
|
|
//
|
|
// Method for adding C++ member constructor
|
|
//
|
|
// INPUTS:
|
|
// name - Name of the constructor (usually same as classname)
|
|
// iname - Renamed version
|
|
// l - parameters
|
|
// --------------------------------------------------------------------
|
|
void RUBY::cpp_constructor(char *name, char *iname, ParmList *l) {
|
|
current = CONSTRUCTOR;
|
|
this->Language::cpp_constructor(name, iname, l);
|
|
current = NO_CPP;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// void RUBY::cpp_destructor(char *name, char *iname)
|
|
//
|
|
// Method for adding C++ member destructor
|
|
//
|
|
// INPUT:
|
|
// name - Name of the destructor (classname)
|
|
// iname - Renamed destructor
|
|
//
|
|
// --------------------------------------------------------------------
|
|
void RUBY::cpp_destructor(char *name, char *newname) {
|
|
current = DESTRUCTOR;
|
|
this->Language::cpp_destructor(name, newname);
|
|
|
|
String freefunc, freeproto, freebody;
|
|
freefunc << "free_" << klass->cname;
|
|
freeproto << "static void " << freefunc << "(" << klass->type << " *);\n";
|
|
freebody << "static void\n"
|
|
<< freefunc << "(" << klass->type << " *ptr) {\n"
|
|
<< tab4 << Swig_name_destroy(name) << "(ptr);\n"
|
|
<< "}\n";
|
|
if (CPlusPlus) {
|
|
"VOIDFUNC(" >> freefunc << ")";
|
|
}
|
|
|
|
klass->header.replace("$freefunc", freefunc.get());
|
|
klass->header.replace("$freeproto", freeproto.get());
|
|
fprintf(f_wrappers, freebody.get());
|
|
|
|
klass->destructor_defined = 1;
|
|
current = NO_CPP;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// void RUBY::cpp_variable(char *name, char *iname, DataType *t)
|
|
//
|
|
// Wrap a C++ data member
|
|
//
|
|
// INPUTS :
|
|
// name = Name of the C++ member
|
|
// iname = Name as used in the interpreter
|
|
// t = Datatype
|
|
//
|
|
// This creates a pair of functions to set/get the variable of a member.
|
|
// --------------------------------------------------------------------
|
|
void RUBY::cpp_variable(char *name, char *iname, DataType *t) {
|
|
current = MEMBER_VAR;
|
|
this->Language::cpp_variable(name, iname, t);
|
|
current = NO_CPP;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
// void RUBY::cpp_static_func(char *name, char *iname, DataType *t, ParmList *l)
|
|
//
|
|
// Wrap a static C++ function
|
|
//
|
|
// INPUTS:
|
|
// name = Real name of the function
|
|
// iname = New name in interpreter
|
|
// t = Return datatype
|
|
// l = Parameters
|
|
// ----------------------------------------------------------------------
|
|
void RUBY::cpp_static_func(char *name, char *iname, DataType *t, ParmList *l) {
|
|
current = STATIC_FUNC;
|
|
this->Language::cpp_static_func(name, iname, t, l);
|
|
current = NO_CPP;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------
|
|
// void RUBY::cpp_declare_const(char *name, char *iname, DataType *t, char *value)
|
|
//
|
|
// Create a C++ constant
|
|
//
|
|
// INPUTS :
|
|
// name = Real name of the constant
|
|
// iname = new name
|
|
// t = Datatype
|
|
// value = value as a string
|
|
//
|
|
// ---------------------------------------------------------------------
|
|
|
|
void RUBY::cpp_declare_const(char *name, char *iname, DataType *type, char *value) {
|
|
current = CLASS_CONST;
|
|
this->Language::cpp_declare_const(name, iname, type, value);
|
|
current = NO_CPP;
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// void RUBY::cpp_static_var(char *name, char *iname, DataType *t)
|
|
//
|
|
// Wrap a static C++ variable
|
|
//
|
|
// INPUT :
|
|
// name = name of the variable
|
|
// iname = interpreter name
|
|
// t = Datatype
|
|
//
|
|
// ---------------------------------------------------------------------
|
|
void RUBY::cpp_static_var(char *name, char *iname, DataType *t) {
|
|
current = STATIC_VAR;
|
|
this->Language::cpp_static_var(name, iname, t);
|
|
current = NO_CPP;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------
|
|
// RUBY::cpp_class_decl(char *name, char *rename, char *type)
|
|
//
|
|
// A forward class declaration
|
|
// -----------------------------------------------------------------------
|
|
void RUBY::cpp_class_decl(char *cname, char *rename, char *type) {
|
|
String valid_name = (rename ? rename : cname);
|
|
validate_const_name(valid_name.get());
|
|
klass->set_name(cname, rename, valid_name.get());
|
|
SET_RCLASS(classes, cname, klass);
|
|
if (type && strlen(type) > 0) {
|
|
String temp;
|
|
temp << type << " " << cname;
|
|
SET_RCLASS(classes, temp.get(), klass);
|
|
}
|
|
String s;
|
|
s << "extern VALUE " << klass->vname << ";\n";
|
|
fprintf(f_header, s.get());
|
|
|
|
klass = new RClass();
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
// void RUBY::pragma(char *target, char *var, char *value)
|
|
//
|
|
// A pragma declaration
|
|
// --------------------------------------------------------------------
|
|
void RUBY::pragma(char *lang, char *cmd, char *value) {
|
|
if (strcmp(lang, "ruby") != 0)
|
|
return;
|
|
|
|
if (strcmp(cmd, "free") == 0) {
|
|
char name[64];
|
|
if (sscanf(value, " %s ", name) != 1) {
|
|
fprintf(stderr, "%s : Line %d. Invalid free pragma.\n",
|
|
input_file, line_number);
|
|
return;
|
|
}
|
|
Setattr(klass->freemethods, name, name);
|
|
} else if (strcmp(cmd, "include") == 0) {
|
|
char name[64];
|
|
if (sscanf(value, " %s ", name) != 1) {
|
|
fprintf(stderr, "%s : Line %d. Invalid include pragma.\n",
|
|
input_file, line_number);
|
|
return;
|
|
}
|
|
klass->includes << tab4 << "rb_include_module($class, "
|
|
<< "rb_eval_string(\"" << name << "\"));\n";
|
|
} else if (strcmp(cmd, "alias") == 0) {
|
|
char alias[64], name[64];
|
|
if (sscanf(value, " %s %s ", alias, name) != 2) {
|
|
fprintf(stderr, "%s : Line %d. Invalid alias pragma.\n",
|
|
input_file, line_number);
|
|
return;
|
|
}
|
|
klass->aliases << tab4 << "rb_define_alias($class, "
|
|
<< "\"" << alias << "\", \"" << name << "\");\n";
|
|
} else if (strcmp(cmd, "pred") == 0) {
|
|
char *tok;
|
|
tok = strtok(value, " \t");
|
|
while (tok) {
|
|
Setattr(klass->predmethods, tok, tok);
|
|
tok = strtok(0, " \t");
|
|
}
|
|
} else if (strcmp(cmd, "debug") == 0) {
|
|
fprintf(f_header, "/* %s */\n", value);
|
|
fprintf(f_wrappers, "/* %s */\n", value);
|
|
fprintf(f_init, "/* %s */\n", value);
|
|
fprintf(stderr, "%s\n", value);
|
|
} else {
|
|
fprintf(stderr, "%s : Line %d. Unrecognized pragma.\n",
|
|
input_file, line_number);
|
|
}
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------
|
|
// RUBY::cpp_pragma(Pragma *plist)
|
|
//
|
|
// Handle C++ pragmas
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void RUBY::cpp_pragma(Pragma *plist) {
|
|
while (plist) {
|
|
pragma(plist->lang.get(), plist->name.get(), plist->value.get());
|
|
plist = plist->next;
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------
|
|
// RUBY::import(char *filename)
|
|
//
|
|
// Imports a SWIG module as a separate file.
|
|
//----------------------------------------------------------------------
|
|
|
|
void RUBY::import(char *filename) {
|
|
if (import_file) delete [] import_file;
|
|
import_file = copy_string(filename);
|
|
}
|
|
|
|
/*
|
|
* Local Variables:
|
|
* c-basic-offset: 2
|
|
* End:
|
|
*/
|