Output anonymous enums defined inside C structs in the global scope, this doesn't change the semantics as the constants defined inside a struct still have global scope in C, but avoids gcc warnings given when compiling the generated code.
1907 lines
63 KiB
C++
1907 lines
63 KiB
C++
/* -----------------------------------------------------------------------------
|
|
* See the LICENSE file for information on copyright, usage and redistribution
|
|
* of SWIG, and the README file for authors - http://www.swig.org/release.html.
|
|
*
|
|
* c.cxx
|
|
*
|
|
* C language module for SWIG.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
char cvsroot_c_cxx[] = "$Id: c.cxx 11186 2009-04-11 10:46:13Z maciekd $";
|
|
|
|
#include <ctype.h>
|
|
#include "swigmod.h"
|
|
|
|
#ifdef IS_SET_TO_ONE
|
|
#undef IS_SET_TO_ONE
|
|
#endif
|
|
#define IS_SET_TO_ONE(n, var) \
|
|
(Cmp(Getattr(n, var), "1") == 0)
|
|
|
|
int SwigType_isbuiltin(SwigType *t) {
|
|
const char* builtins[] = { "void", "short", "int", "long", "char", "float", "double", "bool", 0 };
|
|
int i = 0;
|
|
char *c = Char(t);
|
|
if (!t)
|
|
return 0;
|
|
while (builtins[i]) {
|
|
if (strcmp(c, builtins[i]) == 0)
|
|
return 1;
|
|
i++;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
// Private helpers, could be made public and reused from other language modules in the future.
|
|
namespace
|
|
{
|
|
|
|
// Helper class to output "begin" fragment in the ctor and "end" in the dtor.
|
|
class begin_end_output_guard
|
|
{
|
|
public:
|
|
begin_end_output_guard(File* f, const_String_or_char_ptr begin, const_String_or_char_ptr end)
|
|
: f_(f),
|
|
end_(NewString(end))
|
|
{
|
|
String* const s = NewString(begin);
|
|
Dump(s, f_);
|
|
Delete(s);
|
|
}
|
|
|
|
~begin_end_output_guard()
|
|
{
|
|
Dump(end_, f_);
|
|
Delete(end_);
|
|
}
|
|
|
|
private:
|
|
// Non copyable.
|
|
begin_end_output_guard(const begin_end_output_guard&);
|
|
begin_end_output_guard& operator=(const begin_end_output_guard&);
|
|
|
|
File* const f_;
|
|
String* const end_;
|
|
};
|
|
|
|
// Subclass to output extern "C" guards when compiling as C++.
|
|
class cplusplus_output_guard : private begin_end_output_guard
|
|
{
|
|
public:
|
|
explicit cplusplus_output_guard(File* f)
|
|
: begin_end_output_guard(
|
|
f,
|
|
"#ifdef __cplusplus\n"
|
|
"extern \"C\" {\n"
|
|
"#endif\n\n",
|
|
"#ifdef __cplusplus\n"
|
|
"}\n"
|
|
"#endif\n"
|
|
)
|
|
{
|
|
}
|
|
};
|
|
|
|
// Return the public name to use for the given class.
|
|
//
|
|
// It basically just prepends the namespace, if any, to the class name, and mangles the result.
|
|
String *make_public_class_name(String* nspace, String* classname) {
|
|
String *s = nspace ? NewStringf("%s_", nspace) : NewString("");
|
|
Append(s, classname);
|
|
return s;
|
|
}
|
|
|
|
// String containing one indentation level for the generated code.
|
|
const char* const cindent = " ";
|
|
|
|
} // anonymous namespace
|
|
|
|
class C:public Language {
|
|
static const char *usage;
|
|
|
|
File *f_begin;
|
|
File *f_runtime;
|
|
File *f_header;
|
|
File *f_wrappers;
|
|
File *f_wrappers_cxx;
|
|
File *f_wrappers_types;
|
|
File *f_wrappers_decl;
|
|
File *f_init;
|
|
|
|
String *empty_string;
|
|
String *int_string;
|
|
String *tl_namespace; // optional top level namespace
|
|
|
|
// Contains fully expanded names of the classes for which we have already specialized SWIG_derives_from<>.
|
|
Hash *already_specialized_derives_from;
|
|
|
|
// Used only while generating wrappers for an enum, initially true and reset to false as soon as we see any enum elements.
|
|
bool enum_is_empty;
|
|
|
|
bool except_flag;
|
|
|
|
public:
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* C()
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
C() :
|
|
empty_string(NewString("")),
|
|
int_string(NewString("int")),
|
|
tl_namespace(NULL),
|
|
already_specialized_derives_from(NULL),
|
|
except_flag(true) {
|
|
}
|
|
|
|
|
|
String *getNamespacedName(Node *n)
|
|
{
|
|
if (!n)
|
|
return 0;
|
|
|
|
String *proxyname = NULL;
|
|
if ((proxyname = Getattr(n, "proxyname")))
|
|
return Copy(proxyname);
|
|
|
|
String *symname = Getattr(n, "sym:name");
|
|
String *nspace = Getattr(n, "sym:nspace");
|
|
|
|
if (nspace) {
|
|
// FIXME: using namespace as class name is a hack.
|
|
proxyname = Swig_name_member(tl_namespace, nspace, symname);
|
|
} else {
|
|
proxyname = symname;
|
|
}
|
|
Setattr(n, "proxyname", proxyname);
|
|
Delete(proxyname);
|
|
|
|
return Copy(proxyname);
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* getProxyName()
|
|
*
|
|
* Test to see if a type corresponds to something wrapped with a proxy class.
|
|
* Return NULL if not otherwise the proxy class name, fully qualified with
|
|
* top level namespace name if the nspace feature is used.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
String *getProxyName(SwigType *t) {
|
|
Node *n = NULL;
|
|
|
|
t = SwigType_typedef_resolve_all(t);
|
|
if (!t || !(n = classLookup(t)))
|
|
return NULL;
|
|
|
|
return getNamespacedName(n);
|
|
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* getEnumName()
|
|
*
|
|
* Return the name to use for the enum in the generated code.
|
|
* Also caches it in the node for subsequent access.
|
|
* Returns NULL if the node doesn't correspond to an enum.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
String *getEnumName(Node *n) {
|
|
String *enumname = NULL;
|
|
if (n) {
|
|
enumname = Getattr(n, "enumname");
|
|
if (!enumname) {
|
|
String *symname = Getattr(n, "sym:name");
|
|
if (symname) {
|
|
// Add in class scope when referencing enum if not a global enum
|
|
String *proxyname = 0;
|
|
if (String *name = Getattr(n, "name")) {
|
|
if (String *scopename_prefix = Swig_scopename_prefix(name)) {
|
|
proxyname = getProxyName(scopename_prefix);
|
|
Delete(scopename_prefix);
|
|
}
|
|
}
|
|
if (proxyname) {
|
|
enumname = NewStringf("%s_%s", proxyname, symname);
|
|
} else {
|
|
// global enum or enum in a namespace
|
|
String *nspace = Getattr(n, "sym:nspace");
|
|
if (nspace) {
|
|
if (tl_namespace)
|
|
enumname = NewStringf("%s_%s_%s", tl_namespace, nspace, symname);
|
|
else
|
|
enumname = NewStringf("%s_%s", nspace, symname);
|
|
} else {
|
|
enumname = Copy(symname);
|
|
}
|
|
}
|
|
Setattr(n, "enumname", enumname);
|
|
Delete(enumname);
|
|
}
|
|
}
|
|
}
|
|
|
|
return enumname;
|
|
}
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* substituteResolvedTypeSpecialVariable()
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
void substituteResolvedTypeSpecialVariable(SwigType *classnametype, String *tm, const char *classnamespecialvariable) {
|
|
if (!CPlusPlus) {
|
|
// Just use the original C type when not using C++, we know that this type can be used in the wrappers.
|
|
Clear(tm);
|
|
String* const s = SwigType_str(classnametype, 0);
|
|
Append(tm, s);
|
|
Delete(s);
|
|
return;
|
|
}
|
|
|
|
if (SwigType_isenum(classnametype)) {
|
|
String *enumname = getEnumName(enumLookup(classnametype));
|
|
if (enumname)
|
|
Replaceall(tm, classnamespecialvariable, enumname);
|
|
else
|
|
Replaceall(tm, classnamespecialvariable, NewStringf("int"));
|
|
} else {
|
|
String *classname = getProxyName(classnametype);
|
|
if (classname) {
|
|
Replaceall(tm, classnamespecialvariable, classname); // getProxyName() works for pointers to classes too
|
|
}
|
|
}
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* substituteResolvedType()
|
|
*
|
|
* Substitute the special variable $csclassname with the proxy class name for classes/structs/unions
|
|
* that SWIG knows about. Also substitutes enums with enum name.
|
|
* Otherwise use the $descriptor name for the C# class name. Note that the $&csclassname substitution
|
|
* is the same as a $&descriptor substitution, ie one pointer added to descriptor name.
|
|
* Inputs:
|
|
* pt - parameter type
|
|
* tm - typemap contents that might contain the special variable to be replaced
|
|
* Outputs:
|
|
* tm - typemap contents complete with the special variable substitution
|
|
* Return:
|
|
* substitution_performed - flag indicating if a substitution was performed
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
bool substituteResolvedType(SwigType *pt, String *tm) {
|
|
bool substitution_performed = false;
|
|
SwigType *type = Copy(SwigType_typedef_resolve_all(pt));
|
|
SwigType *strippedtype = SwigType_strip_qualifiers(type);
|
|
|
|
if (Strstr(tm, "$resolved_type")) {
|
|
SwigType *classnametype = Copy(strippedtype);
|
|
substituteResolvedTypeSpecialVariable(classnametype, tm, "$resolved_type");
|
|
substitution_performed = true;
|
|
Delete(classnametype);
|
|
}
|
|
if (Strstr(tm, "$*resolved_type")) {
|
|
SwigType *classnametype = Copy(strippedtype);
|
|
Delete(SwigType_pop(classnametype));
|
|
if (Len(classnametype) > 0) {
|
|
substituteResolvedTypeSpecialVariable(classnametype, tm, "$*resolved_type");
|
|
substitution_performed = true;
|
|
}
|
|
Delete(classnametype);
|
|
}
|
|
if (Strstr(tm, "$&resolved_type")) {
|
|
SwigType *classnametype = Copy(strippedtype);
|
|
SwigType_add_pointer(classnametype);
|
|
substituteResolvedTypeSpecialVariable(classnametype, tm, "$&resolved_type");
|
|
substitution_performed = true;
|
|
Delete(classnametype);
|
|
}
|
|
|
|
Delete(strippedtype);
|
|
Delete(type);
|
|
|
|
return substitution_performed;
|
|
}
|
|
|
|
/* ------------------------------------------------------------
|
|
* main()
|
|
* ------------------------------------------------------------ */
|
|
|
|
virtual void main(int argc, char *argv[]) {
|
|
|
|
// look for certain command line options
|
|
for (int i = 1; i < argc; i++) {
|
|
if (argv[i]) {
|
|
if (strcmp(argv[i], "-help") == 0) {
|
|
Printf(stdout, "%s\n", usage);
|
|
} else if (strcmp(argv[i], "-noexcept") == 0) {
|
|
except_flag = false;
|
|
Swig_mark_arg(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!CPlusPlus)
|
|
except_flag = false;
|
|
|
|
// add a symbol to the parser for conditional compilation
|
|
Preprocessor_define("SWIGC 1", 0);
|
|
if (except_flag)
|
|
Preprocessor_define("SWIG_C_EXCEPT 1", 0);
|
|
if (CPlusPlus)
|
|
Preprocessor_define("SWIG_CPPMODE 1", 0);
|
|
|
|
SWIG_library_directory("c");
|
|
|
|
// add typemap definitions
|
|
SWIG_typemap_lang("c");
|
|
SWIG_config_file("c.swg");
|
|
|
|
allow_overloading();
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------
|
|
* top()
|
|
* --------------------------------------------------------------------- */
|
|
|
|
virtual int top(Node *n) {
|
|
String *module = Getattr(n, "name");
|
|
String *outfile = Getattr(n, "outfile");
|
|
|
|
// initialize I/O
|
|
f_begin = NewFile(outfile, "w", SWIG_output_files());
|
|
if (!f_begin) {
|
|
FileErrorDisplay(outfile);
|
|
SWIG_exit(EXIT_FAILURE);
|
|
}
|
|
f_runtime = NewString("");
|
|
f_init = NewString("");
|
|
f_header = NewString("");
|
|
f_wrappers = NewString("");
|
|
f_wrappers_cxx = NewString("");
|
|
|
|
Swig_banner(f_begin);
|
|
|
|
// Open the file where all wrapper declarations will be written to in the end.
|
|
String* const outfile_h = Getattr(n, "outfile_h");
|
|
File* const f_wrappers_h = NewFile(outfile_h, "w", SWIG_output_files());
|
|
if (!f_wrappers_h) {
|
|
FileErrorDisplay(outfile_h);
|
|
SWIG_exit(EXIT_FAILURE);
|
|
}
|
|
|
|
Swig_banner(f_wrappers_h);
|
|
|
|
Swig_register_filebyname("begin", f_begin);
|
|
Swig_register_filebyname("header", f_header);
|
|
Swig_register_filebyname("wrapper", f_wrappers);
|
|
Swig_register_filebyname("runtime", f_runtime);
|
|
Swig_register_filebyname("init", f_init);
|
|
Swig_register_filebyname("proxy_header", f_wrappers_h);
|
|
|
|
{
|
|
String* const include_guard_name = NewStringf("SWIG_%s_WRAP_H_", Char(module));
|
|
String* const include_guard_begin = NewStringf(
|
|
"#ifndef %s\n"
|
|
"#define %s\n\n",
|
|
include_guard_name,
|
|
include_guard_name
|
|
);
|
|
String* const include_guard_end = NewStringf(
|
|
"\n"
|
|
"#endif /* %s */\n",
|
|
include_guard_name
|
|
);
|
|
|
|
begin_end_output_guard
|
|
include_guard_wrappers_h(f_wrappers_h, include_guard_begin, include_guard_end);
|
|
|
|
// All the struct types used by the functions go to f_wrappers_types so that they're certain to be defined before they're used by any functions. All the
|
|
// functions declarations go directly to f_wrappers_decl and f_wrappers_h_body combines both of them.
|
|
String* const f_wrappers_h_body = NewString("");
|
|
f_wrappers_types = NewString("");
|
|
f_wrappers_decl = NewString("");
|
|
|
|
{
|
|
|
|
cplusplus_output_guard
|
|
cplusplus_guard_wrappers(f_wrappers),
|
|
cplusplus_guard_wrappers_h(f_wrappers_h_body);
|
|
|
|
// emit code for children
|
|
Language::top(n);
|
|
|
|
Dump(f_wrappers_types, f_wrappers_h_body);
|
|
Delete(f_wrappers_types);
|
|
|
|
Dump(f_wrappers_decl, f_wrappers_h_body);
|
|
Delete(f_wrappers_decl);
|
|
} // close extern "C" guards
|
|
|
|
Dump(f_wrappers_h_body, f_wrappers_h);
|
|
Delete(f_wrappers_h_body);
|
|
} // close wrapper header guard
|
|
|
|
// write all to the file
|
|
Dump(f_header, f_runtime);
|
|
Dump(f_wrappers_cxx, f_runtime);
|
|
Wrapper_pretty_print(f_wrappers, f_runtime);
|
|
Dump(f_init, f_runtime);
|
|
Dump(f_runtime, f_begin);
|
|
|
|
// cleanup
|
|
Delete(f_begin);
|
|
Delete(f_header);
|
|
Delete(f_wrappers);
|
|
Delete(f_wrappers_cxx);
|
|
Delete(f_wrappers_h);
|
|
Delete(f_init);
|
|
Delete(f_runtime);
|
|
|
|
return SWIG_OK;
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------
|
|
* globalvariableHandler()
|
|
* ------------------------------------------------------------------------ */
|
|
|
|
virtual int globalvariableHandler(Node *n) {
|
|
// If we can export the variable directly, do it, this will be more convenient to use from C code than accessor functions.
|
|
if (String* const var_decl = make_c_var_decl(n)) {
|
|
Printv(f_wrappers_decl, "SWIGIMPORT ", var_decl, ";\n\n", NIL);
|
|
Delete(var_decl);
|
|
return SWIG_OK;
|
|
}
|
|
|
|
// Otherwise, e.g. if it's of a C++-only type, or a reference, generate accessor functions for it.
|
|
return Language::globalvariableHandler(n);
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------
|
|
* globalfunctionHandler()
|
|
* ------------------------------------------------------------------------ */
|
|
|
|
virtual int globalfunctionHandler(Node *n) {
|
|
SwigType *type = Getattr(n, "type");
|
|
ParmList *parms = Getattr(n, "parms");
|
|
String *arg_list = NewString("");
|
|
String *call = empty_string;
|
|
String *cres = empty_string;
|
|
|
|
call = Swig_cfunction_call(Getattr(n, "name"), parms);
|
|
cres = Swig_cresult(type, "result", call);
|
|
Setattr(n, "wrap:action", cres);
|
|
Setattr(n, "c:globalfun", "1");
|
|
|
|
if (!SwigType_ispointer(type) && !SwigType_isreference(type))
|
|
Setattr(n, "c:retval", "1");
|
|
|
|
functionWrapper(n);
|
|
|
|
Delete(cres);
|
|
Delete(call);
|
|
Delete(arg_list);
|
|
return SWIG_OK;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
* prepend_feature()
|
|
* ---------------------------------------------------------------------- */
|
|
|
|
String* prepend_feature(Node *n) {
|
|
String *prepend_str = Getattr(n, "feature:prepend");
|
|
if (prepend_str) {
|
|
char *t = Char(prepend_str);
|
|
if (*t == '{') {
|
|
Delitem(prepend_str, 0);
|
|
Delitem(prepend_str, DOH_END);
|
|
}
|
|
}
|
|
return (prepend_str ? prepend_str : empty_string);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
* append_feature()
|
|
* ---------------------------------------------------------------------- */
|
|
|
|
String* append_feature(Node *n) {
|
|
String *append_str = Getattr(n, "feature:append");
|
|
if (append_str) {
|
|
char *t = Char(append_str);
|
|
if (*t == '{') {
|
|
Delitem(append_str, 0);
|
|
Delitem(append_str, DOH_END);
|
|
}
|
|
}
|
|
return (append_str ? append_str : empty_string);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
* get_mangled_type()
|
|
* ---------------------------------------------------------------------- */
|
|
|
|
String *get_mangled_type(SwigType *type_arg) {
|
|
String *result = NewString("");
|
|
SwigType *prefix = 0;
|
|
SwigType *type = 0;
|
|
SwigType *tdtype = SwigType_typedef_resolve_all(type_arg);
|
|
if (tdtype)
|
|
type = tdtype;
|
|
else
|
|
type = Copy(type_arg);
|
|
|
|
// special cases for ptr to function as an argument
|
|
if (SwigType_ismemberpointer(type)) {
|
|
SwigType_del_memberpointer(type);
|
|
SwigType_add_pointer(type);
|
|
}
|
|
if (SwigType_ispointer(type)) {
|
|
SwigType_del_pointer(type);
|
|
if (SwigType_isfunction(type)) {
|
|
Printf(result, "f");
|
|
goto ready;
|
|
}
|
|
Delete(type);
|
|
type = Copy(type_arg);
|
|
}
|
|
|
|
prefix = SwigType_prefix(type);
|
|
Replaceall(prefix, ".", "");
|
|
Replaceall(prefix, "const", "c");
|
|
Replaceall(prefix, "volatile", "v");
|
|
Replaceall(prefix, "a(", "a");
|
|
Replaceall(prefix, "m(", "m");
|
|
Replaceall(prefix, "q(", "");
|
|
Replaceall(prefix, ")", "");
|
|
Replaceall(prefix, " ", "");
|
|
Printf(result, "%s", prefix);
|
|
|
|
type = SwigType_base(type);
|
|
if (SwigType_isbuiltin(type))
|
|
Printf(result, "%c", *Char(SwigType_base(type)));
|
|
else if (SwigType_isenum(type))
|
|
Printf(result, "e%s", Swig_scopename_last(type));
|
|
else
|
|
Printf(result, "%s", Char(Swig_name_mangle(SwigType_base(type))));
|
|
|
|
ready:
|
|
if (prefix)
|
|
Delete(prefix);
|
|
if (type)
|
|
Delete(type);
|
|
|
|
return result;
|
|
}
|
|
|
|
virtual void functionWrapperCSpecific(Node *n)
|
|
{
|
|
// this is C function, we don't apply typemaps to it
|
|
String *name = Getattr(n, "sym:name");
|
|
String *wname = Swig_name_wrapper(name);
|
|
SwigType *type = Getattr(n, "type");
|
|
SwigType *return_type = NULL;
|
|
String *arg_names = NULL;
|
|
ParmList *parms = Getattr(n, "parms");
|
|
Parm *p;
|
|
String *proto = NewString("");
|
|
int gencomma = 0;
|
|
bool is_void_return = (SwigType_type(type) == T_VOID);
|
|
|
|
// create new function wrapper object
|
|
Wrapper *wrapper = NewWrapper();
|
|
|
|
// create new wrapper name
|
|
Setattr(n, "wrap:name", wname); //Necessary to set this attribute? Apparently, it's never read!
|
|
|
|
// create function call
|
|
arg_names = Swig_cfunction_call(empty_string, parms);
|
|
if (arg_names) {
|
|
Delitem(arg_names, 0);
|
|
Delitem(arg_names, DOH_END);
|
|
}
|
|
return_type = SwigType_str(type, 0);
|
|
|
|
// emit wrapper prototype and code
|
|
for (p = parms, gencomma = 0; p; p = nextSibling(p)) {
|
|
Printv(proto, gencomma ? ", " : "", SwigType_str(Getattr(p, "type"), 0), " ", Getattr(p, "lname"), NIL);
|
|
gencomma = 1;
|
|
}
|
|
Printv(wrapper->def, return_type, " ", wname, "(", proto, ") {\n", NIL);
|
|
|
|
// attach 'check' typemaps
|
|
Swig_typemap_attach_parms("check", parms, wrapper);
|
|
|
|
// insert constraint checking
|
|
for (p = parms; p; ) {
|
|
String *tm;
|
|
if ((tm = Getattr(p, "tmap:check"))) {
|
|
Replaceall(tm, "$target", Getattr(p, "lname"));
|
|
Replaceall(tm, "$name", name);
|
|
Printv(wrapper->code, tm, "\n", NIL);
|
|
p = Getattr(p, "tmap:check:next");
|
|
}
|
|
else {
|
|
p = nextSibling(p);
|
|
}
|
|
}
|
|
|
|
Append(wrapper->code, prepend_feature(n));
|
|
if (!is_void_return) {
|
|
Printv(wrapper->code, return_type, " result;\n", NIL);
|
|
Printf(wrapper->code, "result = ");
|
|
}
|
|
Printv(wrapper->code, name, "(", arg_names, ");\n", NIL);
|
|
Append(wrapper->code, append_feature(n));
|
|
if (!is_void_return)
|
|
Printf(wrapper->code, "return result;\n");
|
|
Printf(wrapper->code, "}");
|
|
|
|
Wrapper_print(wrapper, f_wrappers);
|
|
|
|
emit_wrapper_func_decl(n, name);
|
|
|
|
// cleanup
|
|
Delete(proto);
|
|
Delete(arg_names);
|
|
Delete(wname);
|
|
Delete(return_type);
|
|
DelWrapper(wrapper);
|
|
}
|
|
|
|
static void functionWrapperPrepareArgs(const ParmList *parms)
|
|
{
|
|
Parm *p;
|
|
int index = 1;
|
|
String *lname = 0;
|
|
|
|
for (p = (Parm*)parms, index = 1; p; (p = nextSibling(p)), index++) {
|
|
if(!(lname = Getattr(p, "lname"))) {
|
|
lname = NewStringf("arg%d", index);
|
|
Setattr(p, "lname", lname);
|
|
}
|
|
}
|
|
}
|
|
|
|
virtual void functionWrapperAppendOverloaded(String *name, const ParmList *parms)
|
|
{
|
|
String *over_suffix = NewString("");
|
|
Parm *p;
|
|
String *mangled;
|
|
|
|
for (p = (Parm*)parms; p; p = nextSibling(p)) {
|
|
if (Getattr(p, "c:objstruct"))
|
|
continue;
|
|
mangled = get_mangled_type(Getattr(p, "type"));
|
|
Printv(over_suffix, "_", mangled, NIL);
|
|
}
|
|
Append(name, over_suffix);
|
|
Delete(over_suffix);
|
|
}
|
|
|
|
static void functionWrapperAddCPPResult(Wrapper *wrapper, const SwigType *type, const String *tm)
|
|
{
|
|
SwigType *cpptype;
|
|
SwigType *tdtype = SwigType_typedef_resolve_all(tm);
|
|
if (tdtype)
|
|
cpptype = tdtype;
|
|
else
|
|
cpptype = (SwigType*)tm;
|
|
if (SwigType_ismemberpointer(type))
|
|
Wrapper_add_local(wrapper, "cppresult", SwigType_str(type, "cppresult"));
|
|
else
|
|
Wrapper_add_local(wrapper, "cppresult", SwigType_str(cpptype, "cppresult"));
|
|
}
|
|
|
|
virtual SwigType *functionWrapperCPPSpecificWrapperReturnTypeGet(Node *n)
|
|
{
|
|
SwigType *type = Getattr(n, "type");
|
|
SwigType *return_type = NewString("");
|
|
String *tm;
|
|
|
|
// set the return type
|
|
if (IS_SET_TO_ONE(n, "c:objstruct")) {
|
|
Printv(return_type, SwigType_str(type, 0), NIL);
|
|
}
|
|
else if ((tm = Swig_typemap_lookup("cmodtype", n, "", 0))) {
|
|
String *ctypeout = Getattr(n, "tmap:cmodtype:out");
|
|
if (ctypeout)
|
|
{
|
|
tm = ctypeout;
|
|
Printf(stdout, "Obscure cmodtype:out found! O.o\n");
|
|
}
|
|
Printf(return_type, "%s", tm);
|
|
// template handling
|
|
Replaceall(return_type, "$tt", SwigType_lstr(type, 0));
|
|
}
|
|
else {
|
|
Swig_warning(WARN_C_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No cmodtype typemap defined for %s\n", SwigType_str(type, 0));
|
|
}
|
|
return return_type;
|
|
}
|
|
|
|
String *get_wrapper_func_return_type(Node *n)
|
|
{
|
|
SwigType *proxy_type = Getattr(n, "c:stype"); // use proxy-type for return type if supplied
|
|
if (proxy_type)
|
|
return SwigType_str(proxy_type, 0);
|
|
|
|
SwigType *type = Getattr(n, "type");
|
|
String *return_type = NewString("");
|
|
String *tm;
|
|
|
|
// set the return type
|
|
if (IS_SET_TO_ONE(n, "c:objstruct")) {
|
|
Printv(return_type, SwigType_str(type, 0), NIL);
|
|
}
|
|
else if ((tm = Swig_typemap_lookup("ctype", n, "", 0))) {
|
|
// handle simple typemap cases
|
|
String *ctypeout = Getattr(n, "tmap:ctype:out");
|
|
if (ctypeout)
|
|
{
|
|
return_type = ctypeout;
|
|
Printf(stdout, "Obscure ctype:out found! O.o\n");
|
|
}
|
|
else
|
|
{
|
|
substituteResolvedType(type, tm);
|
|
return_type = tm;
|
|
}
|
|
}
|
|
else {
|
|
Swig_warning(WARN_C_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No cmodtype typemap defined for %s\n", SwigType_str(type, 0));
|
|
}
|
|
|
|
Replaceall(return_type, "::", "_");
|
|
|
|
return return_type;
|
|
}
|
|
|
|
String *get_wrapper_func_proto(Node *n)
|
|
{
|
|
ParmList *parms = Getattr(n, "parms");
|
|
|
|
Parm *p;
|
|
String *proto = NewString("");
|
|
int gencomma = 0;
|
|
|
|
// attach the standard typemaps
|
|
Swig_typemap_attach_parms("in", parms, 0);
|
|
|
|
// attach 'ctype' typemaps
|
|
Swig_typemap_attach_parms("ctype", parms, 0);
|
|
|
|
|
|
// prepare function definition
|
|
for (p = parms, gencomma = 0; p; ) {
|
|
String *tm;
|
|
SwigType *type = NULL;
|
|
|
|
while (p && checkAttribute(p, "tmap:in:numinputs", "0")) {
|
|
p = Getattr(p, "tmap:in:next");
|
|
}
|
|
if (!p) break;
|
|
|
|
type = Getattr(p, "type");
|
|
if (SwigType_type(type) == T_VOID) {
|
|
p = nextSibling(p);
|
|
continue;
|
|
}
|
|
String *lname = Getattr(p, "lname");
|
|
String *proxy_parm_type = 0;
|
|
String *arg_name = NewString("");
|
|
String* stype = 0;
|
|
|
|
SwigType *tdtype = SwigType_typedef_resolve_all(type);
|
|
if (tdtype)
|
|
type = tdtype;
|
|
|
|
Printf(arg_name, "c%s", lname);
|
|
|
|
if ((tm = Getattr(p, "tmap:ctype"))) { // set the appropriate type for parameter
|
|
tm = Copy(tm);
|
|
}
|
|
else {
|
|
Swig_warning(WARN_C_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(type, 0));
|
|
}
|
|
// use proxy-type for parameter if supplied
|
|
if ((stype = Getattr(p, "c:stype"))) {
|
|
proxy_parm_type = SwigType_lstr(stype, 0);
|
|
} else {
|
|
substituteResolvedType(type, tm);
|
|
proxy_parm_type = tm;
|
|
}
|
|
|
|
Printv(proto, gencomma ? ", " : "", proxy_parm_type, " ", arg_name, NIL);
|
|
gencomma = 1;
|
|
|
|
// apply typemaps for input parameter
|
|
if (Cmp(nodeType(n), "destructor") == 0) {
|
|
p = Getattr(p, "tmap:in:next");
|
|
}
|
|
else if ((tm = Getattr(p, "tmap:in"))) {
|
|
Replaceall(tm, "$input", arg_name);
|
|
p = Getattr(p, "tmap:in:next");
|
|
}
|
|
else {
|
|
Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(type, 0));
|
|
p = nextSibling(p);
|
|
}
|
|
|
|
Delete(arg_name);
|
|
Delete(proxy_parm_type);
|
|
}
|
|
return proto;
|
|
}
|
|
|
|
virtual String *functionWrapperCPPSpecificProxyWrapperCallGet(Node *n, const String *wname, ParmList *parms)
|
|
{
|
|
Parm *p;
|
|
String *call = NewString(wname);
|
|
String *args = NewString("");
|
|
int gencomma = 0;
|
|
|
|
Printv(call, "(", NIL);
|
|
|
|
// attach typemaps to cast wrapper call with proxy types
|
|
Swig_typemap_attach_parms("cmodtype", parms, 0);
|
|
|
|
// prepare function definition
|
|
for (p = parms, gencomma = 0; p; ) {
|
|
String *tm;
|
|
SwigType *type = NULL;
|
|
|
|
while (p && checkAttribute(p, "tmap:in:numinputs", "0")) {
|
|
p = Getattr(p, "tmap:in:next");
|
|
}
|
|
if (!p) break;
|
|
|
|
type = Getattr(p, "type");
|
|
if (SwigType_type(type) == T_VOID) {
|
|
p = nextSibling(p);
|
|
continue;
|
|
}
|
|
String *lname = Getattr(p, "lname");
|
|
String *c_parm_type = NewString("");
|
|
String *arg_name = NewString("");
|
|
|
|
SwigType *tdtype = SwigType_typedef_resolve_all(type);
|
|
if (tdtype)
|
|
type = tdtype;
|
|
|
|
Printf(arg_name, "c%s", lname);
|
|
|
|
// set the appropriate type for parameter
|
|
if ((tm = Getattr(p, "tmap:cmodtype"))) {
|
|
Printv(c_parm_type, NewString("("), tm, NewString(")"), NIL);
|
|
// template handling
|
|
Replaceall(c_parm_type, "$tt", SwigType_lstr(type, 0));
|
|
}
|
|
else {
|
|
Swig_warning(WARN_C_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No cmodtype typemap defined for %s\n", SwigType_str(type, 0));
|
|
}
|
|
|
|
Printv(args, gencomma ? ", " : "", c_parm_type, arg_name, NIL);
|
|
gencomma = 1;
|
|
|
|
// apply typemaps for input parameter
|
|
if (Cmp(nodeType(n), "destructor") == 0) {
|
|
p = Getattr(p, "tmap:in:next");
|
|
}
|
|
else if ((tm = Getattr(p, "tmap:in"))) {
|
|
Replaceall(tm, "$input", arg_name);
|
|
p = Getattr(p, "tmap:in:next");
|
|
}
|
|
else {
|
|
Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(type, 0));
|
|
p = nextSibling(p);
|
|
}
|
|
|
|
Delete(arg_name);
|
|
Delete(c_parm_type);
|
|
}
|
|
Printv(call, args, ")", NIL);
|
|
|
|
return call;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
* emit_wrapper_func_decl()
|
|
*
|
|
* Declares the wrapper function, using the C types used for it, in the header.
|
|
* The node here is a function declaration.
|
|
* ---------------------------------------------------------------------- */
|
|
void emit_wrapper_func_decl(Node *n, String *name)
|
|
{
|
|
// C++ function wrapper proxy code
|
|
String *wname = IS_SET_TO_ONE(n, "c:globalfun") ? Swig_name_wrapper(name) : Copy(name);
|
|
String *preturn_type = get_wrapper_func_return_type(n);
|
|
String *pproto = get_wrapper_func_proto(n);
|
|
String *wrapper_call = NewString("");
|
|
|
|
// add function declaration to the proxy header file
|
|
Printv(f_wrappers_decl, preturn_type, " ", wname, "(", pproto, ");\n\n", NIL);
|
|
|
|
// cleanup
|
|
Delete(wname);
|
|
Delete(pproto);
|
|
Delete(wrapper_call);
|
|
Delete(preturn_type);
|
|
}
|
|
|
|
|
|
virtual void functionWrapperCPPSpecificWrapper(Node *n, String *name)
|
|
{
|
|
// C++ function wrapper
|
|
String *storage = Getattr(n, "storage");
|
|
SwigType *type = Getattr(n, "type");
|
|
SwigType *otype = Copy(type);
|
|
SwigType *return_type = functionWrapperCPPSpecificWrapperReturnTypeGet(n);
|
|
String *wname = IS_SET_TO_ONE(n, "c:globalfun") ? Swig_name_wrapper(name) : Copy(name);
|
|
String *arg_names = NewString("");
|
|
ParmList *parms = Getattr(n, "parms");
|
|
Parm *p;
|
|
int gencomma = 0;
|
|
bool is_void_return = (SwigType_type(type) == T_VOID);
|
|
bool return_object = false;
|
|
// create new function wrapper object
|
|
Wrapper *wrapper = NewWrapper();
|
|
|
|
// create new wrapper name
|
|
Setattr(n, "wrap:name", wname);
|
|
|
|
// add variable for holding result of original function 'cppresult'
|
|
if (!is_void_return && !IS_SET_TO_ONE(n, "c:objstruct")) {
|
|
String *tm;
|
|
if ((tm = Swig_typemap_lookup("cppouttype", n, "", 0))) {
|
|
functionWrapperAddCPPResult(wrapper, type, tm);
|
|
return_object = checkAttribute(n, "tmap:cppouttype:retobj", "1");
|
|
}
|
|
else {
|
|
Swig_warning(WARN_C_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No cppouttype typemap defined for %s\n", SwigType_str(type, 0));
|
|
}
|
|
}
|
|
|
|
// create wrapper function prototype
|
|
Printv(wrapper->def, "SWIGEXPORTC ", return_type, " ", wname, "(", NIL);
|
|
|
|
// attach the standard typemaps
|
|
emit_attach_parmmaps(parms, wrapper);
|
|
Setattr(n, "wrap:parms", parms); //never read again?!
|
|
|
|
// attach 'ctype' typemaps
|
|
Swig_typemap_attach_parms("cmodtype", parms, wrapper);
|
|
|
|
// prepare function definition
|
|
for (p = parms, gencomma = 0; p; ) {
|
|
String *tm;
|
|
|
|
while (p && checkAttribute(p, "tmap:in:numinputs", "0")) {
|
|
p = Getattr(p, "tmap:in:next");
|
|
}
|
|
if (!p) break;
|
|
|
|
SwigType *type = Getattr(p, "type");
|
|
if (SwigType_type(type) == T_VOID) {
|
|
p = nextSibling(p);
|
|
continue;
|
|
}
|
|
String *lname = Getattr(p, "lname");
|
|
String *c_parm_type = NewString("");
|
|
String *proxy_parm_type = NewString("");
|
|
String *arg_name = NewString("");
|
|
|
|
SwigType *tdtype = SwigType_typedef_resolve_all(type);
|
|
if (tdtype)
|
|
type = tdtype;
|
|
|
|
Printf(arg_name, "c%s", lname);
|
|
|
|
// set the appropriate type for parameter
|
|
if ((tm = Getattr(p, "tmap:cmodtype"))) {
|
|
Printv(c_parm_type, tm, NIL);
|
|
// template handling
|
|
Replaceall(c_parm_type, "$tt", SwigType_lstr(type, 0));
|
|
}
|
|
else {
|
|
Swig_warning(WARN_C_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No cmodtype typemap defined for %s\n", SwigType_str(type, 0));
|
|
}
|
|
|
|
// use proxy-type for parameter if supplied
|
|
String* stype = Getattr(p, "c:stype");
|
|
if (stype) {
|
|
Printv(proxy_parm_type, SwigType_str(stype, 0), NIL);
|
|
}
|
|
else {
|
|
Printv(proxy_parm_type, c_parm_type, NIL);
|
|
}
|
|
|
|
Printv(arg_names, gencomma ? ", " : "", arg_name, NIL);
|
|
Printv(wrapper->def, gencomma ? ", " : "", c_parm_type, " ", arg_name, NIL);
|
|
gencomma = 1;
|
|
|
|
// apply typemaps for input parameter
|
|
if (Cmp(nodeType(n), "destructor") == 0) {
|
|
p = Getattr(p, "tmap:in:next");
|
|
}
|
|
else if ((tm = Getattr(p, "tmap:in"))) {
|
|
Replaceall(tm, "$input", arg_name);
|
|
Setattr(p, "emit:input", arg_name);
|
|
Printf(wrapper->code, "%s\n", tm);
|
|
p = Getattr(p, "tmap:in:next");
|
|
}
|
|
else {
|
|
Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(type, 0));
|
|
p = nextSibling(p);
|
|
}
|
|
|
|
Delete(arg_name);
|
|
Delete(proxy_parm_type);
|
|
Delete(c_parm_type);
|
|
}
|
|
|
|
Printv(wrapper->def, ")", NIL);
|
|
Printv(wrapper->def, " {", NIL);
|
|
|
|
if (Cmp(nodeType(n), "destructor") != 0) {
|
|
// emit variables for holding parameters
|
|
emit_parameter_variables(parms, wrapper);
|
|
|
|
// emit variable for holding function return value
|
|
emit_return_variable(n, return_type, wrapper);
|
|
}
|
|
|
|
// insert constraint checking
|
|
for (p = parms; p; ) {
|
|
String *tm;
|
|
if ((tm = Getattr(p, "tmap:check"))) {
|
|
Replaceall(tm, "$target", Getattr(p, "lname"));
|
|
Replaceall(tm, "$name", name);
|
|
Printv(wrapper->code, tm, "\n", NIL);
|
|
p = Getattr(p, "tmap:check:next");
|
|
}
|
|
else {
|
|
p = nextSibling(p);
|
|
}
|
|
}
|
|
|
|
// create action code
|
|
String *action = Getattr(n, "wrap:action");
|
|
if (!action)
|
|
action = NewString("");
|
|
|
|
String *cbase_name = Getattr(n, "c:base_name");
|
|
if (cbase_name) {
|
|
Replaceall(action, "arg1)->", NewStringf("(%s*)arg1)->", Getattr(n, "c:inherited_from")));
|
|
Replaceall(action, Getattr(n, "name"), cbase_name);
|
|
}
|
|
|
|
// handle special cases of cpp return result
|
|
if (Cmp(nodeType(n), "constructor") != 0) {
|
|
if (SwigType_isenum(SwigType_base(type))){
|
|
if (return_object)
|
|
Replaceall(action, "result =", "cppresult = (int)");
|
|
else Replaceall(action, "result =", "cppresult = (int*)");
|
|
}
|
|
else if (return_object && Getattr(n, "c:retval") && !SwigType_isarray(type)
|
|
&& (Cmp(storage, "static") != 0)) {
|
|
// returning object by value
|
|
String *str = SwigType_str(SwigType_add_reference(SwigType_base(type)), "_result_ref");
|
|
String *lstr = SwigType_lstr(type, 0);
|
|
if (Cmp(Getattr(n, "kind"), "variable") == 0) {
|
|
Delete(action);
|
|
action = NewStringf("{const %s = %s;", str, Swig_cmemberget_call(Getattr(n, "name"), type, 0, 0));
|
|
}
|
|
else {
|
|
String *call_str = NewStringf("{const %s = %s", str,
|
|
SwigType_ispointer(SwigType_typedef_resolve_all(otype)) ? "*" : "");
|
|
Replaceall(action, "result =", call_str);
|
|
Delete(call_str);
|
|
}
|
|
if (Getattr(n, "nested"))
|
|
Replaceall(action, "=", NewStringf("= *(%s)(void*) &", SwigType_str(otype, 0)));
|
|
Printf(action, "cppresult = (%s*) &_result_ref;}", lstr);
|
|
Delete(str);
|
|
Delete(lstr);
|
|
}
|
|
else
|
|
Replaceall(action, "result =", "cppresult = ");
|
|
}
|
|
|
|
// prepare action code to use, e.g. insert try-catch blocks
|
|
action = emit_action(n);
|
|
|
|
// emit output typemap if needed
|
|
if (!is_void_return && (Cmp(Getattr(n, "c:objstruct"), "1") != 0)) {
|
|
String *tm;
|
|
if ((tm = Swig_typemap_lookup_out("out", n, "cppresult", wrapper, action))) {
|
|
Replaceall(tm, "$result", "result");
|
|
Printf(wrapper->code, "%s", tm);
|
|
if (Len(tm))
|
|
Printf(wrapper->code, "\n");
|
|
}
|
|
else {
|
|
Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(type, 0), Getattr(n, "name"));
|
|
}
|
|
}
|
|
else {
|
|
Append(wrapper->code, action);
|
|
}
|
|
|
|
String *except = Getattr(n, "feature:except");
|
|
if (Getattr(n, "throws") || except) {
|
|
if (!except || (Cmp(except, "0") != 0))
|
|
Printf(wrapper->code, "if (SWIG_exc.handled) {\nSWIG_rt_stack_pop();\nlongjmp(SWIG_rt_env, 1);\n}\n");
|
|
}
|
|
|
|
// insert cleanup code
|
|
for (p = parms; p; ) {
|
|
String *tm;
|
|
if ((tm = Getattr(p, "tmap:freearg"))) {
|
|
if (tm && (Len(tm) != 0)) {
|
|
String *input = NewStringf("c%s", Getattr(p, "lname"));
|
|
Replaceall(tm, "$source", Getattr(p, "lname"));
|
|
Replaceall(tm, "$input", input);
|
|
Delete(input);
|
|
Printv(wrapper->code, tm, "\n", NIL);
|
|
}
|
|
p = Getattr(p, "tmap:freearg:next");
|
|
}
|
|
else {
|
|
p = nextSibling(p);
|
|
}
|
|
}
|
|
|
|
if (!is_void_return)
|
|
Append(wrapper->code, "return result;\n");
|
|
|
|
Append(wrapper->code, "}\n");
|
|
|
|
Wrapper_print(wrapper, f_wrappers);
|
|
|
|
// cleanup
|
|
Delete(arg_names);
|
|
Delete(wname);
|
|
Delete(return_type);
|
|
Delete(otype);
|
|
DelWrapper(wrapper);
|
|
}
|
|
|
|
virtual void functionWrapperCPPSpecificMarkFirstParam(Node *n)
|
|
{
|
|
bool is_global = IS_SET_TO_ONE(n, "c:globalfun"); // possibly no longer neede
|
|
String *storage = Getattr(n, "storage");
|
|
ParmList *parms = Getattr(n, "parms");
|
|
|
|
// mark the first parameter as object-struct
|
|
if (!is_global && storage && (Cmp(storage, "static") != 0)) {
|
|
if (IS_SET_TO_ONE(n, "ismember") &&
|
|
(Cmp(nodeType(n), "constructor") != 0)) {
|
|
Setattr(parms, "c:objstruct", "1");
|
|
if (!Getattr(parms, "lname"))
|
|
Setattr(parms, "lname", "arg1");
|
|
SwigType *stype = Copy(Getattr(Swig_methodclass(n), "sym:name"));
|
|
SwigType_add_pointer(stype);
|
|
Setattr(parms, "c:stype", stype);
|
|
}
|
|
}
|
|
}
|
|
|
|
virtual void functionWrapperCPPSpecific(Node *n)
|
|
{
|
|
ParmList *parms = Getattr(n, "parms");
|
|
String *name = Copy(Getattr(n, "sym:name"));
|
|
SwigType *type = Getattr(n, "type");
|
|
SwigType *tdtype = NULL;
|
|
|
|
functionWrapperCPPSpecificMarkFirstParam(n);
|
|
|
|
// mangle name if function is overloaded
|
|
if (Getattr(n, "sym:overloaded")) {
|
|
if (!Getattr(n, "copy_constructor")) {
|
|
functionWrapperAppendOverloaded(name, parms);
|
|
}
|
|
}
|
|
|
|
// resolve correct type
|
|
if((tdtype = SwigType_typedef_resolve_all(type)))
|
|
Setattr(n, "type", tdtype);
|
|
|
|
// make sure lnames are set
|
|
functionWrapperPrepareArgs(parms);
|
|
|
|
// C++ function wrapper
|
|
functionWrapperCPPSpecificWrapper(n, name);
|
|
emit_wrapper_func_decl(n, name);
|
|
|
|
Delete(name);
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------
|
|
* functionWrapper()
|
|
* ---------------------------------------------------------------------- */
|
|
|
|
virtual int functionWrapper(Node *n) {
|
|
|
|
if (CPlusPlus) {
|
|
functionWrapperCPPSpecific(n);
|
|
}
|
|
else {
|
|
functionWrapperCSpecific(n);
|
|
}
|
|
|
|
return SWIG_OK;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------
|
|
* copy_node()
|
|
* --------------------------------------------------------------------- */
|
|
|
|
Node *copy_node(Node *node) {
|
|
Node *new_node = NewHash();
|
|
Setattr(new_node, "name", Copy(Getattr(node, "name")));
|
|
Setattr(new_node, "ismember", Copy(Getattr(node, "ismember")));
|
|
Setattr(new_node, "view", Copy(Getattr(node, "view")));
|
|
Setattr(new_node, "kind", Copy(Getattr(node, "kind")));
|
|
Setattr(new_node, "access", Copy(Getattr(node, "access")));
|
|
Setattr(new_node, "parms", Copy(Getattr(node, "parms")));
|
|
Setattr(new_node, "type", Copy(Getattr(node, "type")));
|
|
Setattr(new_node, "decl", Copy(Getattr(node, "decl")));
|
|
String *cif = Getattr(node, "c:inherited_from");
|
|
if (cif)
|
|
Setattr(new_node, "c:inherited_from", Copy(cif));
|
|
return new_node;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------
|
|
* is_in()
|
|
*
|
|
* tests if given name already exists in one of child nodes of n
|
|
* --------------------------------------------------------------------- */
|
|
|
|
Hash *is_in(String *name, Node *n) {
|
|
Hash *h;
|
|
for (h = firstChild(n); h; h = nextSibling(h)) {
|
|
if (Cmp(name, Getattr(h, "name")) == 0)
|
|
return h;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------
|
|
* make_c_var_decl()
|
|
*
|
|
* Return the C declaration for the given node of "variable" kind.
|
|
*
|
|
* If the variable has a type not representable in C, returns NULL, the caller must check for this!
|
|
*
|
|
* This function accounts for two special cases:
|
|
* 1. If the type is an anonymous enum, "int" is used instead.
|
|
* 2. If the type is an array, its bounds are stripped.
|
|
* --------------------------------------------------------------------- */
|
|
String *make_c_var_decl(Node *n) {
|
|
String *name = Getattr(n, "name");
|
|
SwigType *type = Getattr(n, "type");
|
|
String *type_str = SwigType_str(type, 0);
|
|
|
|
if (Getattr(n, "unnamedinstance")) {
|
|
// If this is an anonymous enum, we can declare the variable as int even though we can't reference this type.
|
|
if (Strncmp(type_str, "enum $", 6) != 0) {
|
|
// Otherwise we're out of luck, with the current approach of exposing the variables directly we simply can't do it, we would need to use accessor
|
|
// functions instead to support this.
|
|
Swig_error(Getfile(n), Getline(n), "Variables of anonymous non-enum types are not supported.\n");
|
|
return SWIG_ERROR;
|
|
}
|
|
|
|
const char * const unnamed_end = strchr(Char(type_str) + 6, '$');
|
|
if (!unnamed_end) {
|
|
Swig_error(Getfile(n), Getline(n), "Unsupported anonymous enum type \"%s\".\n", type_str);
|
|
return SWIG_ERROR;
|
|
}
|
|
|
|
String* const int_type_str = NewStringf("int%s", unnamed_end + 1);
|
|
Delete(type_str);
|
|
type_str = int_type_str;
|
|
} else {
|
|
// Don't bother with checking if type is representable in C if we're wrapping C and not C++ anyhow: of course it is.
|
|
if (CPlusPlus) {
|
|
if (SwigType_isreference(type))
|
|
return NIL;
|
|
|
|
SwigType *btype = SwigType_base(type);
|
|
const bool can_be_repr_in_c = SwigType_isbuiltin(btype) || SwigType_isenum(btype);
|
|
Delete(btype);
|
|
if (!can_be_repr_in_c)
|
|
return NIL;
|
|
}
|
|
}
|
|
|
|
String* const var_decl = NewStringEmpty();
|
|
if (SwigType_isarray(type)) {
|
|
String *dims = Strchr(type_str, '[');
|
|
char *c = Char(type_str);
|
|
c[Len(type_str) - Len(dims) - 1] = '\0';
|
|
Printv(var_decl, c, " ", name, "[]", NIL);
|
|
} else {
|
|
Printv(var_decl, type_str, " ", name, NIL);
|
|
}
|
|
|
|
Delete(type_str);
|
|
|
|
return var_decl;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------
|
|
* emit_c_struct_def()
|
|
*
|
|
* Append the declarations of C struct members to the given string.
|
|
* Notice that this function has a side effect of outputting all enum declarations inside the struct into f_wrappers_types directly.
|
|
* This is done to avoid gcc warnings "declaration does not declare anything" given for the anonymous enums inside the structs.
|
|
* --------------------------------------------------------------------- */
|
|
|
|
void emit_c_struct_def(String* out, Node *n) {
|
|
for ( Node* node = firstChild(n); node; node = nextSibling(node)) {
|
|
String* const ntype = nodeType(node);
|
|
if (Cmp(ntype, "cdecl") == 0) {
|
|
String* const var_decl = make_c_var_decl(node);
|
|
Printv(out, cindent, var_decl, ";\n", NIL);
|
|
Delete(var_decl);
|
|
} else if (Cmp(ntype, "enum") == 0) {
|
|
// This goes directly into f_wrappers_types, before this struct declaration.
|
|
emit_one(node);
|
|
} else {
|
|
// WARNING: proxy declaration can be different than original code
|
|
if (Cmp(nodeType(node), "extend") == 0)
|
|
emit_c_struct_def(out, node);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------
|
|
* classHandler()
|
|
* --------------------------------------------------------------------- */
|
|
|
|
virtual int classHandler(Node *n) {
|
|
String *name = getNamespacedName(n);
|
|
|
|
if (CPlusPlus) {
|
|
// inheritance support: attach all members from base classes to this class
|
|
if (List *baselist = Getattr(n, "bases")) {
|
|
// We may need to specialize SWIG_derives_from<> for this class: its unique check() method will return true iff it's given the name of any subclasses of
|
|
// this class. Notice that it may happen that all our base classes are ignored, in which case we don't do anything.
|
|
int specialize_derives_from = -1;
|
|
|
|
Iterator i;
|
|
for (i = First(baselist); i.item; i = Next(i)) {
|
|
// look for member variables and functions
|
|
Node *node;
|
|
for (node = firstChild(i.item); node; node = nextSibling(node)) {
|
|
if ((Cmp(Getattr(node, "kind"), "variable") == 0)
|
|
|| (Cmp(Getattr(node, "kind"), "function") == 0)) {
|
|
if ((Cmp(Getattr(node, "access"), "public") == 0)
|
|
&& (Cmp(Getattr(node, "storage"), "static") != 0)) {
|
|
Node *new_node = copy_node(node);
|
|
String *parent_name = Getattr(parentNode(node), "name");
|
|
Hash *dupl_name_node = is_in(Getattr(node, "name"), n);
|
|
// if there's a duplicate inherited name, due to the C++ multiple
|
|
// inheritance, change both names to avoid ambiguity
|
|
if (dupl_name_node) {
|
|
String *cif = Getattr(dupl_name_node, "c:inherited_from");
|
|
String *old_name = Getattr(dupl_name_node, "name");
|
|
if (cif && parent_name && (Cmp(cif, parent_name) != 0)) {
|
|
Setattr(dupl_name_node, "name", NewStringf("%s%s", cif ? cif : "", old_name));
|
|
Setattr(dupl_name_node, "c:base_name", old_name);
|
|
Setattr(new_node, "name", NewStringf("%s%s", parent_name, old_name));
|
|
Setattr(new_node, "c:base_name", old_name);
|
|
Setattr(new_node, "c:inherited_from", parent_name);
|
|
Setattr(new_node, "sym:name", Getattr(new_node, "name"));
|
|
Setattr(new_node, "sym:symtab", Getattr(n, "symtab"));
|
|
set_nodeType(new_node, "cdecl");
|
|
appendChild(n, new_node);
|
|
}
|
|
}
|
|
else {
|
|
Setattr(new_node, "c:inherited_from", parent_name);
|
|
Setattr(new_node, "sym:name", Getattr(new_node, "name"));
|
|
Setattr(new_node, "sym:symtab", Getattr(n, "symtab"));
|
|
set_nodeType(new_node, "cdecl");
|
|
appendChild(n, new_node);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Account for this base class in the RTTI checks.
|
|
String* const name = Getattr(i.item, "sym:name");
|
|
if (name) {
|
|
if (specialize_derives_from == -1) {
|
|
// Check if we hadn't specialized it already. Somewhat surprisingly, this can happen for an instantiation of a template with default parameter(s)
|
|
// if it appears both without them and with the default values explicitly given as it happens in e.g. template_default2 unit test.
|
|
SwigType* const fulltype = Swig_symbol_template_deftype(Getattr(n, "name"), NULL);
|
|
String* const fulltype_str = SwigType_str(fulltype, NULL);
|
|
Delete(fulltype);
|
|
|
|
if (!already_specialized_derives_from || !Getattr(already_specialized_derives_from, fulltype_str)) {
|
|
if (!already_specialized_derives_from) {
|
|
already_specialized_derives_from = NewHash();
|
|
}
|
|
|
|
Setattr(already_specialized_derives_from, fulltype_str, "1");
|
|
|
|
Printv(f_wrappers_cxx,
|
|
"template<> struct SWIG_derives_from< ", fulltype_str, " > {\n",
|
|
cindent, "static bool check(const char* type) {\n",
|
|
cindent, cindent, "return ",
|
|
NIL);
|
|
|
|
specialize_derives_from = true;
|
|
} else {
|
|
specialize_derives_from = false;
|
|
}
|
|
|
|
Delete(fulltype_str);
|
|
}
|
|
else if (specialize_derives_from) {
|
|
// Continue the already started specialization.
|
|
Printv(f_wrappers_cxx, " ||\n", cindent, cindent, NIL);
|
|
}
|
|
|
|
if (specialize_derives_from) {
|
|
Printv(f_wrappers_cxx, "strcmp(type, \"", name, "\") == 0", NIL);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (specialize_derives_from == true) {
|
|
// End SWIG_derives_from specialization.
|
|
Printv(f_wrappers_cxx, ";\n }\n};\n\n", NIL);
|
|
}
|
|
}
|
|
|
|
// declare type for specific class in the proxy header
|
|
Printv(f_wrappers_types, "typedef struct SwigObj_", name, " ", name, ";\n\n", NIL);
|
|
|
|
Delete(name);
|
|
return Language::classHandler(n);
|
|
} else {
|
|
// this is C struct, just declare it in the proxy
|
|
String* struct_def = NewStringEmpty();
|
|
String* const tdname = Getattr(n, "tdname");
|
|
if (tdname)
|
|
Append(struct_def, "typedef struct {\n");
|
|
else
|
|
Printv(struct_def, "struct ", name, " {\n", NIL);
|
|
emit_c_struct_def(struct_def, n);
|
|
if (tdname)
|
|
Printv(struct_def, "} ", tdname, ";\n\n", NIL);
|
|
else
|
|
Append(struct_def, "};\n\n");
|
|
|
|
Printv(f_wrappers_types, struct_def, NIL);
|
|
Delete(struct_def);
|
|
|
|
Delete(name);
|
|
}
|
|
return SWIG_OK;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------
|
|
* staticmemberfunctionHandler()
|
|
* --------------------------------------------------------------------- */
|
|
|
|
virtual int staticmemberfunctionHandler(Node *n) {
|
|
SwigType *type = Getattr(n, "type");
|
|
SwigType *tdtype;
|
|
tdtype = SwigType_typedef_resolve_all(type);
|
|
if (tdtype)
|
|
type = tdtype;
|
|
if (type) {
|
|
if (!SwigType_ispointer(type) && !SwigType_isreference(type))
|
|
Setattr(n, "c:retval", "1");
|
|
}
|
|
return Language::staticmemberfunctionHandler(n);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------
|
|
* memberfunctionHandler()
|
|
* --------------------------------------------------------------------- */
|
|
|
|
virtual int memberfunctionHandler(Node *n) {
|
|
SwigType *type = Getattr(n, "type");
|
|
SwigType *tdtype;
|
|
tdtype = SwigType_typedef_resolve_all(type);
|
|
if (tdtype)
|
|
type = tdtype;
|
|
if (type) {
|
|
if (!SwigType_ispointer(type) && !SwigType_isreference(type))
|
|
Setattr(n, "c:retval", "1");
|
|
}
|
|
return Language::memberfunctionHandler(n);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------
|
|
* staticmembervariableHandler()
|
|
* --------------------------------------------------------------------- */
|
|
|
|
virtual int staticmembervariableHandler(Node *n) {
|
|
SwigType *type = Getattr(n, "type");
|
|
SwigType *tdtype = SwigType_typedef_resolve_all(type);
|
|
if (tdtype) {
|
|
type = tdtype;
|
|
Setattr(n, "type", type);
|
|
}
|
|
SwigType *btype = SwigType_base(type);
|
|
if (SwigType_isarray(type) && !SwigType_isbuiltin(btype)) {
|
|
// this hack applies to member objects array (not ptrs.)
|
|
SwigType_add_pointer(btype);
|
|
SwigType_add_array(btype, NewStringf("%s", SwigType_array_getdim(type, 0)));
|
|
Setattr(n, "type", btype);
|
|
}
|
|
if (type) {
|
|
if (!SwigType_ispointer(type) && !SwigType_isreference(type))
|
|
Setattr(n, "c:retval", "1");
|
|
}
|
|
Delete(type);
|
|
Delete(btype);
|
|
return Language::staticmembervariableHandler(n);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------
|
|
* membervariableHandler()
|
|
* --------------------------------------------------------------------- */
|
|
|
|
virtual int membervariableHandler(Node *n) {
|
|
SwigType *type = Getattr(n, "type");
|
|
SwigType *tdtype = SwigType_typedef_resolve_all(type);
|
|
if (tdtype) {
|
|
type = tdtype;
|
|
Setattr(n, "type", type);
|
|
}
|
|
SwigType *btype = SwigType_base(type);
|
|
if (SwigType_isarray(type) && !SwigType_isbuiltin(btype)) {
|
|
// this hack applies to member objects array (not ptrs.)
|
|
SwigType_add_pointer(btype);
|
|
SwigType_add_array(btype, NewStringf("%s", SwigType_array_getdim(type, 0)));
|
|
Setattr(n, "type", btype);
|
|
}
|
|
if (type) {
|
|
if (!SwigType_ispointer(type) && !SwigType_isreference(type))
|
|
Setattr(n, "c:retval", "1");
|
|
}
|
|
Delete(type);
|
|
Delete(btype);
|
|
return Language::membervariableHandler(n);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------
|
|
* constructorHandler()
|
|
* --------------------------------------------------------------------- */
|
|
|
|
virtual int constructorHandler(Node *n) {
|
|
String *access = Getattr(n, "access");
|
|
if (Cmp(access, "private") == 0)
|
|
return SWIG_NOWRAP;
|
|
if (Getattr(n, "copy_constructor"))
|
|
return copyconstructorHandler(n);
|
|
|
|
Node *klass = Swig_methodclass(n);
|
|
String *newclassname = Getattr(klass, "sym:name");
|
|
String *sobj_name = NewString("");
|
|
String *ctype;
|
|
String *stype;
|
|
String *code = NewString("");
|
|
String *constr_name = NewString("");
|
|
String *arg_lnames = NewString("");
|
|
ParmList *parms = Getattr(n, "parms");
|
|
String *nspace = Getattr(klass, "sym:nspace");
|
|
|
|
// prepare argument names
|
|
Append(arg_lnames, Swig_cfunction_call(empty_string, parms));
|
|
|
|
// set the function return type to the pointer to struct
|
|
Printf(sobj_name, "SwigObj");
|
|
ctype = Copy(sobj_name);
|
|
SwigType_add_pointer(ctype);
|
|
Setattr(n, "type", ctype);
|
|
Setattr(n, "c:objstruct", "1");
|
|
stype = make_public_class_name(nspace, newclassname);
|
|
SwigType_add_pointer(stype);
|
|
Setattr(n, "c:stype", stype);
|
|
|
|
// Modify the constructor name if necessary
|
|
constr_name = Swig_name_construct(nspace, newclassname);
|
|
|
|
Setattr(n, "name", newclassname);
|
|
Setattr(n, "sym:name", constr_name);
|
|
|
|
// generate action code
|
|
if (!Getattr(klass, "c:create")) {
|
|
Setattr(klass, "c:create", "1");
|
|
}
|
|
Printv(code, "result = SWIG_create_object(new ", Getattr(klass, "classtype"), arg_lnames,
|
|
", \"", newclassname, "\");\n",
|
|
NIL);
|
|
|
|
Setattr(n, "wrap:action", code);
|
|
functionWrapper(n);
|
|
|
|
Delete(arg_lnames);
|
|
Delete(constr_name);
|
|
Delete(code);
|
|
Delete(stype);
|
|
Delete(ctype);
|
|
Delete(sobj_name);
|
|
return SWIG_OK;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------
|
|
* copyconstructorHandler()
|
|
* --------------------------------------------------------------------- */
|
|
|
|
virtual int copyconstructorHandler(Node *n) {
|
|
Node *klass = Swig_methodclass(n);
|
|
String *classname = Getattr(klass, "classtype");
|
|
String *newclassname = Getattr(klass, "sym:name");
|
|
String *sobj_name = NewString("");
|
|
String *ctype;
|
|
String *stype;
|
|
String *code = NewString("");
|
|
String *constr_name = NewString("");
|
|
ParmList *parms = Getattr(n, "parms");
|
|
String *nspace = Getattr(klass, "sym:nspace");
|
|
|
|
Setattr(parms, "lname", "arg1");
|
|
|
|
// set the function return type to the pointer to struct
|
|
Printf(sobj_name, "SwigObj");
|
|
ctype = Copy(sobj_name);
|
|
SwigType_add_pointer(ctype);
|
|
Setattr(n, "type", ctype);
|
|
Setattr(n, "c:objstruct", "1");
|
|
stype = make_public_class_name(nspace, newclassname);
|
|
SwigType_add_pointer(stype);
|
|
Setattr(n, "c:stype", stype);
|
|
|
|
// modify the constructor if necessary
|
|
constr_name = Swig_name_copyconstructor(nspace, newclassname);
|
|
|
|
Setattr(n, "name", newclassname);
|
|
Setattr(n, "sym:name", constr_name);
|
|
|
|
// generate action code
|
|
if (!Getattr(klass, "c:create")) {
|
|
Setattr(klass, "c:create", "1");
|
|
}
|
|
Printv(code, "result = SWIG_create_object(new ", classname, "((", classname, " const &)*arg1)",
|
|
", \"", newclassname, "\");\n",
|
|
NIL);
|
|
|
|
Setattr(n, "wrap:action", code);
|
|
functionWrapper(n);
|
|
|
|
Delete(constr_name);
|
|
Delete(code);
|
|
Delete(stype);
|
|
Delete(ctype);
|
|
Delete(sobj_name);
|
|
return SWIG_OK;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------
|
|
* destructorHandler()
|
|
* --------------------------------------------------------------------- */
|
|
|
|
virtual int destructorHandler(Node *n) {
|
|
if (Cmp(Getattr(n, "access"), "public") != 0)
|
|
return SWIG_NOWRAP;
|
|
|
|
Node *klass = Swig_methodclass(n);
|
|
String *newclassname = Getattr(klass, "sym:name");
|
|
String *sobj_name = NewString("");
|
|
String *ctype;
|
|
String *stype;
|
|
String *code = NewString("");
|
|
String *destr_name = NewString("");
|
|
String *nspace = Getattr(klass, "sym:nspace");
|
|
Parm *p;
|
|
|
|
// create first argument
|
|
Printf(sobj_name, "SwigObj");
|
|
ctype = Copy(sobj_name);
|
|
SwigType_add_pointer(ctype);
|
|
p = NewParm(ctype, "self", n);
|
|
Setattr(p, "lname", "arg1");
|
|
stype = make_public_class_name(nspace, newclassname);
|
|
SwigType_add_pointer(stype);
|
|
Setattr(p, "c:stype", stype);
|
|
Setattr(p, "c:objstruct", "1");
|
|
Setattr(n, "parms", p);
|
|
Setattr(n, "type", "void");
|
|
|
|
// modify the destructor name if necessary
|
|
destr_name = Swig_name_destroy(nspace, newclassname);
|
|
|
|
Setattr(n, "name", NULL);
|
|
Setattr(n, "sym:name", destr_name);
|
|
|
|
// create action code
|
|
Printv(code, "SWIG_destroy_object< ", Getattr(klass, "classtype"), " >(carg1);", NIL);
|
|
Setattr(n, "wrap:action", code);
|
|
|
|
functionWrapper(n);
|
|
|
|
Delete(p);
|
|
Delete(destr_name);
|
|
Delete(code);
|
|
Delete(stype);
|
|
Delete(ctype);
|
|
Delete(sobj_name);
|
|
return SWIG_OK;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------
|
|
* enumDeclaration()
|
|
* --------------------------------------------------------------------- */
|
|
|
|
virtual int enumDeclaration(Node *n) {
|
|
if (ImportMode)
|
|
return SWIG_OK;
|
|
|
|
if (getCurrentClass() && (cplus_mode != PUBLIC))
|
|
return SWIG_NOWRAP;
|
|
|
|
// Preserve the typedef if we have it in the input.
|
|
String* const tdname = Getattr(n, "tdname");
|
|
if (tdname) {
|
|
Printv(f_wrappers_types, "typedef ", NIL);
|
|
}
|
|
Printv(f_wrappers_types, "enum", NIL);
|
|
|
|
if (String* const name = Getattr(n, "name")) {
|
|
String* const enumname = Swig_name_mangle(name);
|
|
Printv(f_wrappers_types, " ", enumname, NIL);
|
|
Delete(enumname);
|
|
}
|
|
|
|
// We don't know here if we're going to have any non-ignored enum elements, so let enumvalueDeclaration() itself reset this flag if it does get called, this
|
|
// is simpler than trying to determine it here, even if it's a bit ugly because we generate the opening brace there, but the closing one here.
|
|
enum_is_empty = true;
|
|
|
|
// Emit each enum item.
|
|
Language::enumDeclaration(n);
|
|
|
|
if (!enum_is_empty) {
|
|
Printv(f_wrappers_types, "\n}", NIL);
|
|
}
|
|
|
|
if (tdname) {
|
|
String* const enumname = Swig_name_mangle(tdname);
|
|
Printv(f_wrappers_types, " ", enumname, NIL);
|
|
Delete(enumname);
|
|
}
|
|
Printv(f_wrappers_types, ";\n\n", NIL);
|
|
|
|
return SWIG_OK;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------
|
|
* enumvalueDeclaration()
|
|
* --------------------------------------------------------------------- */
|
|
|
|
virtual int enumvalueDeclaration(Node *n) {
|
|
if (Cmp(Getattr(n, "ismember"), "1") == 0 && Cmp(Getattr(n, "access"), "public") != 0)
|
|
return SWIG_NOWRAP;
|
|
Swig_require("enumvalueDeclaration", n, "*value", "?enumvalueex", "?enumvalue", NIL);
|
|
|
|
enum_is_empty = false;
|
|
|
|
if (GetFlag(n, "firstenumitem"))
|
|
Printv(f_wrappers_types, " {\n", NIL);
|
|
else
|
|
Printv(f_wrappers_types, ",\n", NIL);
|
|
|
|
String* const enumitemname = Getattr(n, "value");
|
|
Printv(f_wrappers_types, cindent, Swig_name_mangle(enumitemname), NIL);
|
|
|
|
// We only use "enumvalue", which comes from the input, and not "enumvalueex" synthesized by SWIG itself because C should use the correct value for the enum
|
|
// items without an explicit one anyhow (and "enumvalueex" can't be always used as is in C code for enum elements inside a class or even a namespace).
|
|
String *value = Getattr(n, "enumvalue");
|
|
if (value) {
|
|
String* const cvalue = Copy(value);
|
|
|
|
// Due to what seems to be a bug in SWIG parser, char values for enum elements lose their quotes, i.e.
|
|
//
|
|
// enum { x = 'a', y = '\x62' };
|
|
//
|
|
// in input results in value being just "a" or "\x62". Try to repair this brokenness.
|
|
if (*Char(value) == '\\') {
|
|
Push(cvalue, "'");
|
|
Append(cvalue, "'");
|
|
} else if (Len(value) == 1 && !Swig_symbol_clookup(enumitemname, NULL)) {
|
|
Push(cvalue, "'");
|
|
Append(cvalue, "'");
|
|
}
|
|
|
|
// Boolean constants can't appear in C code neither, so replace them with their values in the simplest possible case. This is not exhaustive, of course,
|
|
// but better than nothing and doing the right thing is not simple at all as we'd need to really parse the expression, just textual substitution wouldn't
|
|
// be enough (consider e.g. an enum element called "very_true" and another one using it as its value).
|
|
if (Cmp(value, "true") == 0) {
|
|
Clear(cvalue);
|
|
Append(cvalue, "1");
|
|
} else if (Cmp(value, "false") == 0) {
|
|
Clear(cvalue);
|
|
Append(cvalue, "0");
|
|
}
|
|
|
|
Printv(f_wrappers_types, " = ", cvalue, NIL);
|
|
|
|
Delete(cvalue);
|
|
}
|
|
|
|
Swig_restore(n);
|
|
return SWIG_OK;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------
|
|
* constantWrapper()
|
|
* --------------------------------------------------------------------- */
|
|
|
|
virtual int constantWrapper(Node *n) {
|
|
String *name = Getattr(n, "sym:name");
|
|
String *value = Getattr(n, "value");
|
|
Printv(f_wrappers_decl, "#define ", name, " ", value, "\n", NIL);
|
|
return SWIG_OK;
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------
|
|
* classDeclaration()
|
|
* --------------------------------------------------------------------- */
|
|
|
|
virtual int classDeclaration(Node *n) {
|
|
String *name = NewString("");
|
|
String *classtype = Getattr(n, "classtype");
|
|
String *prefix = 0;
|
|
if (classtype) {
|
|
prefix = Swig_scopename_prefix(classtype);
|
|
if (prefix)
|
|
Printf(name, "%s_", Swig_name_mangle(prefix));
|
|
}
|
|
Append(name, Swig_name_mangle(Getattr(n, "sym:name")));
|
|
Setattr(n, "sym:name", name);
|
|
return Language::classDeclaration(n);
|
|
}
|
|
|
|
/* ---------------------------------------------------------------------
|
|
* extendDirective()
|
|
*
|
|
* The idea is to extend the class with additional variables, using
|
|
* SwigObj structs. This is not implemented yet.
|
|
* --------------------------------------------------------------------- */
|
|
|
|
virtual int extendDirective(Node *n) {
|
|
return Language::extendDirective(n);
|
|
}
|
|
|
|
}; /* class C */
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* swig_c() - Instantiate module
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
static Language *new_swig_c() {
|
|
return new C();
|
|
}
|
|
|
|
extern "C" Language *swig_c(void) {
|
|
return new_swig_c();
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Static member variables
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
const char *C::usage = (char *) "\
|
|
C Options (available with -c)\n\
|
|
-noexcept - do not generate exception handling code\n\
|
|
\n";
|
|
|