Skip to content

Instantly share code, notes, and snippets.

@fennecdjay
Created November 13, 2017 17:17
Show Gist options
  • Save fennecdjay/bebd57b3c13af09d8cced529ec486beb to your computer and use it in GitHub Desktop.
Save fennecdjay/bebd57b3c13af09d8cced529ec486beb to your computer and use it in GitHub Desktop.
#include "swigmod.h"
static const char *usage = "\
Gwion Options (available with -gwion)\n\
[no additional options]\n\
\n";
class GWION : public Language {
enum Wrap_mode {
NO_CPP,
MEMBER_FUNC,
DEFAULT_CONSTRUCTOR,
CONSTRUCTOR,
DESTRUCTOR,
MEMBER_VAR,
CLASS_CONST,
STATIC_FUNC,
STATIC_VAR
};
File *f_begin;
File *f_runtime;
File *f_header;
File *f_wrappers;
File *f_init;
File *f_classInit;
String *PrefixPlusUnderscore;
enum Wrap_mode current;
bool is_cpp;
String* nspc;
String *gw_class_name;
String *default_ctor;
String *dtor;
public:
GWION() {
f_begin = 0;
f_runtime = 0;
f_header = 0;
f_wrappers = 0;
f_init = 0;
f_classInit = 0;
PrefixPlusUnderscore = 0;
current = NO_CPP;
is_cpp = 0;
nspc = NULL;
dtor = NULL;
gw_class_name = NULL;
default_ctor = NULL;
}
~GWION() {
Delete(gw_class_name);
gw_class_name = NULL;
}
virtual void main(int argc, char *argv[]) {
SWIG_library_directory("gwion");
for (int i = 1; i < argc; i++) {
if (argv[i]) {
if (strcmp(argv[i], "-help") == 0) {
fputs(usage, stdout);
}
else if (strcmp(argv[i], "-nspc") == 0) {
if (argv[i + 1]) {
nspc = NewString(argv[i+1]);
Swig_mark_arg(i);
Swig_mark_arg(i+1);
i++;
}
}
else if (strcmp(argv[i], "-c++") == 0) {
is_cpp = 1;
Swig_mark_arg(i);
}
}
}
SWIG_config_file("gwion.swg");
SWIG_typemap_lang("gwion");
allow_overloading();
}
virtual int top(Node *n) {
String *outfile = Getattr(n, "outfile");
f_begin = NewFile(outfile, "w", SWIG_output_files());
if (!f_begin) {
FileErrorDisplay(outfile);
SWIG_exit(EXIT_FAILURE);
}
f_runtime = NewString("");
f_init = NewString("");
f_classInit = NewString("");
f_header = NewString("");
f_wrappers = NewString("");
Swig_register_filebyname("header", f_header);
Swig_register_filebyname("wrapper", f_wrappers);
Swig_register_filebyname("begin", f_begin);
Swig_register_filebyname("runtime", f_runtime);
Swig_register_filebyname("init", f_init);
Swig_register_filebyname("classInit", f_classInit);
Swig_name_register("wrapper", "gw_%f");
Swig_name_register("construct", "%n%c_ctor");
Swig_name_register("destroy", "%n%c_dtor");
current = NO_CPP;
if(!is_cpp) {
Printf(f_init, "IMPORT {\n");
Replaceall(outfile, ".c", "");
Printf(f_wrappers,
"static struct Type_ t_%s = { \"%s\", SZ_INT, &t_object };\n",
outfile, outfile);
Printf(f_init,
"CHECK_BB(importer_class_ini(importer, &t_%s, NULL, NULL))\n",
outfile);
} else {
Printf(f_init, "m_bool CPPIMPORT(Importer importer) {\n");
if(nspc)
Printf(f_init,
"CHECK_BB(importer_class_ini(importer, &t_%s, NULL, NULL))\n",
nspc);
}
Language::top(n);
if(!is_cpp) {
Printf(f_header, "#include \"type.h\"\n#include \"instr.h\""
"\n#include \"import.h\"\n\n");
Printf(f_init, "CHECK_BB(importer_class_end(importer))\n");
} else {
Printf(f_header, "#include \"Gwion.hpp\"\n\n");
if(nspc) {
Printf(f_wrappers,
"static struct Type_ t_%s = { (m_str)\"%s\", SZ_INT, &t_object };\n",
nspc, nspc);
Printf(f_init, "CHECK_BB(importer_class_end(importer))\n");
Delete(nspc);
}
}
Printf(f_init, "return 1;\n}\n");
if(is_cpp) {
Printf(f_init, "extern \"C\" IMPORT{ CPPIMPORT(importer);}\n");
}
//Dump(f_runtime, f_begin);
Dump(f_header, f_begin);
Dump(f_wrappers, f_begin);
Wrapper_pretty_print(f_init, f_begin);
Delete(f_header);
Delete(f_wrappers);
Delete(f_init);
Delete(f_classInit);
Delete(f_runtime);
Delete(f_begin);
return SWIG_OK;
}
String *strip(const DOHconst_String_or_char_ptr name) {
String *s = Copy(name);
if (Strncmp(name, PrefixPlusUnderscore, Len(PrefixPlusUnderscore)) != 0) {
return s;
}
Replaceall(s, PrefixPlusUnderscore, "");
return s;
}
String* getWname(Node* n) {
String *iname = Getattr(n, "sym:name");
String *overname = 0;
String *wname = Swig_name_wrapper(iname);
String* gwstrip = Getattr(n, "feature:gwstrip");
Replaceall(wname, gwstrip, "");
if (Getattr(n, "sym:overloaded"))
overname = Getattr(n, "sym:overname");
else if (!addSymbol(iname, n))
return NULL;
if (overname) {
String* oname = NewString(overname);
Replaceall(overname, "__SWIG_", "");
Append(wname, overname);
Delete(overname);
}
Setattr(n, "wrap:name", wname);
return wname;
}
void startFunction(Wrapper* f, String* wname) {
// Printf(f->def, "// start function\n");
char fun[5];
if(current == DEFAULT_CONSTRUCTOR)
strcpy(fun, "CTOR");
else if(current == DESTRUCTOR)
strcpy(fun, "DTOR");
else if(current == MEMBER_VAR || current == MEMBER_FUNC ||
current == CONSTRUCTOR)
strcpy(fun, "MFUN");
else
strcpy(fun, "SFUN");
Printf(f->def, "static %s(%s) {\n", fun, wname);
}
virtual int functionWrapper(Node *n) {
bool is_static = GetFlag(n, "isstatic") != 0;
bool is_member = GetFlag(n, "ismember") != 0;
bool is_setter = GetFlag(n, "memberset") != 0 || GetFlag(n, "varset") != 0;
bool is_getter = GetFlag(n, "memberget") != 0 || GetFlag(n, "varget") != 0;
String* ctor_attr = Getattr(n, "feature:gwctor");
String* member_attr = Getattr(n, "feature:gwmember");
String *name = Getattr(n, "name");
String *iname = Getattr(n, "sym:name");
ParmList *l = Getattr(n, "parms");
SwigType *d = Getattr(n, "type");
String *wname = getWname(n);
Node* interrest = is_setter ?
current == MEMBER_VAR ? nextSibling(l) : l : n;
String* ffi = Swig_typemap_lookup("ffitype", interrest, "", 0);
/*
if(l && is_member && !is_static && current != CONSTRUCTOR && current != DESTRUCTOR
) // 'this' handled in Gwion
l = nextSibling(l);
*/
Parm *p;
String *tm;
int i;
Wrapper *f = NewWrapper();
if(current != DESTRUCTOR)
emit_parameter_variables(l, f);
emit_attach_parmmaps(l, f);
Setattr(n, "wrap:parms", l);
int num_arguments = emit_num_arguments(l);
int varargs = emit_isvarargs(l);
int start = (current == MEMBER_FUNC ||
current == MEMBER_VAR || current == DESTRUCTOR ||
(member_attr && !ctor_attr)) ? 1 : 0;
Setattr(n, "wrap:name", wname);
// don't print abstract ctor
if (current == CONSTRUCTOR && num_arguments == 0) {
current = DEFAULT_CONSTRUCTOR;
if(Getattr(getCurrentClass(), "abstracts"))
return SWIG_OK;
default_ctor = wname;
}
if(member_attr)
Printf(f->def, "static MFUN(%s) {\n", wname);
else if(ctor_attr)
Printf(f->def, "static MFUN(%s) {\n", wname);
else
startFunction(f, wname);
// inheritance
Node* base_class = getCurrentClass();
String* parent_name = base_class ? Getattr(Getattr(base_class, "base_class") ?
Getattr(base_class, "base_class")
: getCurrentClass(), "name") : NULL;
if(num_arguments && !is_getter)
Printf(f->def, " m_uint offset = SZ_INT;");
if(current == MEMBER_VAR || (member_attr && !ctor_attr))
num_arguments++;
if (member_attr && !(is_getter || is_getter))
Printf(f->code, "arg1 = (%s*)GW_%s(o);\n",
member_attr, member_attr);
for (i = 0, p = l; i < num_arguments; i++) {
if(!p)break;
while (checkAttribute(p, "tmap:in:numinputs", "0")) {
p = Getattr(p, "tmap:in:next");
}
SwigType *pt = Getattr(p, "type");
String *ln = Getattr(p, "lname");
if (i < start) {
if(!member_attr)
Printf(f->code, "arg1 = (%s*)GW_%s(o);\n",
Getattr(getCurrentClass(), "name"),
parent_name);
} else {
/* Look for an input typemap */
if ((tm = Getattr(p, "tmap:in"))) {
Replaceall(tm, "$target", ln);
Printf(f->code, "%s\n", tm);
} else {
Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
break;
}
}
p = nextSibling(p);
}
if(current == MEMBER_FUNC)
Printf(f->code, "arg1 = (%s*)GW_%s(o);\n", Getattr(getCurrentClass(), "name"), parent_name);
/* Check for trailing varargs */
if (varargs) {
if (p && (tm = Getattr(p, "tmap:in"))) {
Replaceall(tm, "$input", "varargs");
Printv(f->code, tm, "\n", NIL);
}
}
/* Insert constraint checking code */
for (p = l; p;) {
if ((tm = Getattr(p, "tmap:check"))) {
Replaceall(tm, "$target", Getattr(p, "lname"));
Printv(f->code, tm, "\n", NIL);
p = Getattr(p, "tmap:check:next");
} else {
p = nextSibling(p);
}
}
/* Insert cleanup code */
String *cleanup = NewString("");
for (p = l; p;) {
if ((tm = Getattr(p, "tmap:freearg"))) {
Printv(cleanup, tm, "\n", NIL);
p = Getattr(p, "tmap:freearg:next");
} else {
p = nextSibling(p);
}
}
/* Insert argument output code */
String *outarg = NewString("");
for (p = l; p;) {
if ((tm = Getattr(p, "tmap:argout"))) {
Replaceall(tm, "$target", "resultobj");
Replaceall(tm, "$arg", Getattr(p, "emit:input"));
Replaceall(tm, "$input", Getattr(p, "emit:input"));
Printv(outarg, tm, "\n", NIL);
p = Getattr(p, "tmap:argout:next");
} else {
p = nextSibling(p);
}
}
String *actioncode = emit_action(n);
if(is_getter && current == STATIC_VAR) {
String* class_name = NewString(") ");
Append(class_name, Getattr(getCurrentClass(), "name"));
Append(class_name, "::");
Replaceall(actioncode, ")", class_name);
Delete(class_name);
}
if(is_setter && Cmp(Getattr(n, "storage"), "static")) {
Printf(f->code, "result = arg%i;\n", is_member ? 2 : 1);
//Replaceall(f->code, "RETURN = ;\n");
}
// if(is_setter)
// Replaceall(actioncode, "arg1", "result = arg1");
if (current == DEFAULT_CONSTRUCTOR) {
default_ctor = NewString(wname);
// actioncode = 0;
Clear(actioncode);
if(!Getattr(getCurrentClass(), "abstracts")) {
if(is_cpp)
Printf(actioncode, "if(o->type_ref->xid == t_%s.xid)GW_%s(o) = new %s();\n",
Getattr(getCurrentClass(), "name"),
parent_name,
Getattr(getCurrentClass(), "name"));
else
Printf(actioncode, "if(o->type_ref->xid == t_%s.xid)"
"GW_%s(o) = malloc(sizeof(%s));\n",
Getattr(getCurrentClass(), "name"),
parent_name,
Getattr(getCurrentClass(), "name"));
}
// printf("Handle default ctor\n"); exit(21);
} else if (current == DESTRUCTOR) {
actioncode = 0;
dtor = wname;
} else {
if ((tm = Swig_typemap_lookup_out("out", is_setter ? interrest : n, Swig_cresult_name(), f, actioncode))) {
actioncode = 0;
Replaceall(tm, "$result", "resultobj");
if (GetFlag(n, "feature:new")) {
Replaceall(tm, "$owner", "1");
} else {
Replaceall(tm, "$owner", "0");
}
Printf(f->code, "%s\n", tm);
Printf(stderr, "%s\n", tm);
} else if (!is_setter) {
Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number,
"Unable to use return type %s in function %s.\n",
SwigType_str(d, 0), name);
}
}
if (actioncode) {
Append(f->code, actioncode);
Delete(actioncode);
}
emit_return_variable(n, is_setter ? Getattr(interrest, "type") : d, f);
if(current == DESTRUCTOR) {
if(is_cpp)
Printf(f->code,"if(GW_%s(o)) {\ndelete (%s*)GW_%s(o);\n GW_%s(o) = NULL;\}\n",
parent_name, Getattr(getCurrentClass(), "name"), parent_name, parent_name);
else
Printf(f->code,"if(GW_%s(o)) {\nfree(GW_%s(o));\n GW_%s(o) = NULL;\}\n",
parent_name, Getattr(getCurrentClass(), "name"), parent_name, parent_name);
}
/* Output argument output code */
Printv(f->code, outarg, NIL);
/* Output cleanup code */
Printv(f->code, cleanup, NIL);
/* Look to see if there is any newfree cleanup code */
if (GetFlag(n, "feature:new")) {
if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
Printf(f->code, "%s\n", tm);
}
}
/* See if there is any return cleanup code */
if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
Printf(f->code, "%s\n", tm);
}
/* Close the function */
Printf(f->code, "}\n");
/* Substitute the cleanup code */
Replaceall(f->code, "$cleanup", cleanup);
/* Substitute the function name */
Replaceall(f->code, "$symname", iname);
Replaceall(f->code, "$result", "resultobj");
// handle non default ctor
if(current == CONSTRUCTOR || ctor_attr) {
String* my_ctor = NewStringf("GW_%s(o) = ", parent_name ?
parent_name : ctor_attr);
Replaceall(f->code, "result =", my_ctor);
Delete(my_ctor);
}
/* Dump the function out */
Wrapper_print(f, f_wrappers);
if(current == MEMBER_VAR || current == STATIC_VAR) {
Replaceall(name, "::", "");
Replaceall(name, Getattr(Swig_methodclass(n), "name"), "");
}
/* Now register the function with the interpreter. */
if (current != DESTRUCTOR && !(current == DEFAULT_CONSTRUCTOR)) {
/*
if(!(tm = Swig_typemap_lookup("ffitype", n, "", 0))) {
Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number,
"Unable to use type %s as a return type (set ffitype). (%s)\n",
getCurrentClass() ?
SwigType_str(Getattr(getCurrentClass(), "name"), 0): NULL, name);
Printf(stderr, "%s %i %i %i\n", name, is_member, is_getter, is_setter);
return SWIG_ERROR;
}
*/
String* tmp_name = current == STATIC_FUNC ? strip(Getattr(n, "sym:name"))
: NewString(name);
String *f_target = current == NO_CPP ? f_init : f_classInit;
Printf(f_target, "CHECK_BB(importer_func_ini(importer, \"%s\", \"%s\", "
// "(m_uint)%s))\n", ffi ? ffi : "void", name, wname);
"(m_uint)%s))\n", ffi ? ffi : "void", tmp_name, wname);
Delete(tmp_name);
//for (i = start, p = start ? nextSibling(l) : l; i < num_arguments; i++) {
for (i = start, p = start ? nextSibling(l) : l; i < num_arguments; i++) {
if(!p)break;
String* p_type = Getattr(p, "type");
String* p_name = Getattr(p, "lname");
char _ln[64];
sprintf(_ln, "%s%i", "arg", i);
if((tm = Swig_typemap_lookup("ffitype", p, "", 0)))
p_type = tm;
Printf(f_target,
"CHECK_BB(importer_func_arg(importer, \"%s\", \"%s\"))\n",
p_type, (current == STATIC_FUNC || current == STATIC_VAR) ?
p_name : _ln);
p = nextSibling(p);
}
const char* _flag = (current == MEMBER_FUNC || current == MEMBER_VAR ||
current == CONSTRUCTOR || ctor_attr || member_attr) ?
"ae_flag_member" : "ae_flag_static";
String* flag = NewString(_flag);
Printf(f_target,
"CHECK_BB(importer_func_end(importer, %s))\n",
flag);
Delete(flag);
}
Delete(cleanup);
Delete(outarg);
Delete(wname);
DelWrapper(f);
return SWIG_OK;
}
/* ------------------------------------------------------------
* constantWrapper()
* ------------------------------------------------------------ */
virtual int constantWrapper(Node *n) {
Swig_require("constantWrapper", n, "*sym:name", "type", "value", NIL);
String *symname = Getattr(n, "sym:name");
SwigType *type = Getattr(n, "type");
String *value = Getattr(n, "value");
//bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0);
/*
if (SwigType_type(type) == T_MPOINTER) {
// Special hook for member pointer
String *wname = Swig_name_wrapper(symname);
Printf(f_header, "static %s = %s;\n", SwigType_str(type, wname), value);
value = wname;
} else if (SwigType_type(type) == T_CHAR && is_enum_item) {
type = NewSwigType(T_INT);
Setattr(n, "type", type);
} else {
Printf(stderr, "%s %s %s %i\n", symname, type, value, is_enum_item);
}
*/
// Perform constant typemap substitution
String *tm = Swig_typemap_lookup("constant", n, value, 0);
String *ff = Swig_typemap_lookup("ffitype", n, value, 0);
if(!ff) {
Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number,
"'fftype' undefined for constant value %s = %s\n",
SwigType_str(type, 0), value);
}
if (tm) {
Replaceall(tm, "$symname", symname);
Replaceall(tm, "$value", value);
Printf(f_init, "%s\n", tm);
Printf(f_init,
"CHECK_BB(importer_item_ini(importer, \"%s\", \"%s\"))\n",
ff, symname);
Printf(f_init,
"CHECK_BB(importer_item_end(importer, ae_flag_const | ae_flag_static, "
" (const m_uint*)%s_value))\n\n", symname);
} else {
Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value %s = %s\n", SwigType_str(type, 0), value);
return SWIG_ERROR;
}
Swig_restore(n);
return SWIG_OK;
}
virtual int classHandler(Node *n) {
String* basename = NULL;
String *symname = Getattr(n, "sym:name");
String * gwctor = Getattr(n, "feature:gwctor");
if (!addSymbol(symname, n))
return SWIG_ERROR;
PrefixPlusUnderscore = NewStringf("%s_", getClassPrefix());
Node * base_class = NULL;
/* Handle inheritance */
List *baselist = Getattr(n, "bases");
if (baselist && Len(baselist) > 0) {
Iterator base = First(baselist);
while (base.item) {
basename = Getattr(base.item, "name");
Printf(f_wrappers,
"static struct Type_ t_%s = { (m_str)\"%s\", SZ_INT, &t_%s };\n",
symname, symname, basename);
base_class = base.item;
base = Next(base);
}
Setattr(n, "base_class", base_class);
} else {
Printf(f_wrappers,
"static struct Type_ t_%s = { (m_str)\"%s\", SZ_INT, &t_object };\n",
symname, symname);
}
Printf(f_wrappers, "static m_int o_%s_swig;\n", symname);
if(!baselist)
Printf(f_wrappers, "#define GW_%s(a) *(void**)(o->data + o_%s_swig)\n",
symname, symname);
Language::classHandler(n);
/* Done, close the class and dump its definition to the init function */
if(GetFlag(n, "abstracts"))
Printf(f_init, "SET_FLAG((&t_%s), ae_flag_abstract);\n", symname);
Printf(f_init,
"CHECK_BB(importer_class_ini(importer, &t_%s, %s, %s));\n",
symname, default_ctor ? default_ctor : "NULL", dtor ? dtor : "NULL");
Printf(f_init, "CHECK_BB(importer_item_ini(importer,"
"\"int\", \"@Swig_%s_Object\"))\n", symname, symname);
Printf(f_init, "CHECK_BB((o_%s_swig = "
"importer_item_end(importer, ae_flag_member, NULL)))\n",
symname, symname);
Dump(f_classInit, f_init);
Clear(f_classInit);
if(!GetFlag(n, "feature:noclassend")) {
if(gw_class_name)
Delete(gw_class_name);
Printf(f_init, "CHECK_BB(importer_class_end(importer));\n");
gw_class_name = NewString(symname);
}
Delete(PrefixPlusUnderscore);
PrefixPlusUnderscore = 0;
dtor = NULL;
default_ctor = NULL;
return SWIG_OK;
}
virtual int memberfunctionHandler(Node *n) {
current = MEMBER_FUNC;
Language::memberfunctionHandler(n);
current = NO_CPP;
return SWIG_OK;
}
virtual int constructorHandler(Node *n) {
current = CONSTRUCTOR;
Language::constructorHandler(n);
current = NO_CPP;
return SWIG_OK;
}
virtual int destructorHandler(Node *n) {
current = DESTRUCTOR;
Language::destructorHandler(n);
current = NO_CPP;
return SWIG_OK;
}
virtual int membervariableHandler(Node *n) {
current = MEMBER_VAR;
Language::membervariableHandler(n);
current = NO_CPP;
return SWIG_OK;
}
virtual int staticmemberfunctionHandler(Node *n) {
current = STATIC_FUNC;
Language::staticmemberfunctionHandler(n);
current = NO_CPP;
return SWIG_OK;
}
virtual int memberconstantHandler(Node *n) {
current = CLASS_CONST;
constantWrapper(n);
current = NO_CPP;
return SWIG_OK;
}
virtual int staticmembervariableHandler(Node *n) {
current = STATIC_VAR;
Language::staticmembervariableHandler(n);
current = NO_CPP;
return SWIG_OK;
}
};
/* -----------------------------------------------------------------------------
* swig_gwion() - Instantiate module
* ----------------------------------------------------------------------------- */
static Language *new_swig_gwion() {
return new GWION();
}
extern "C" Language *swig_gwion(void) {
return new_swig_gwion();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment