949 lines
24 KiB
C++
949 lines
24 KiB
C++
#include <xemil.h>
|
|
|
|
#include <map>
|
|
#include <string>
|
|
#include <fstream>
|
|
#include <sstream>
|
|
#include <locale>
|
|
#include <iostream>
|
|
|
|
struct typeinfo {
|
|
std::string type;
|
|
std::string name;
|
|
std::string struct_name;
|
|
std::string widget_type;
|
|
int pointer;
|
|
int unsigned_num;
|
|
};
|
|
|
|
struct property {
|
|
typeinfo type;
|
|
int common;
|
|
};
|
|
|
|
struct handler {
|
|
int common;
|
|
int has_arg;
|
|
typeinfo arg_type;
|
|
};
|
|
|
|
std::map<std::string, std::ofstream> files;
|
|
|
|
std::map<std::string, property> props;
|
|
std::map<std::string, handler> handlers;
|
|
|
|
std::locale locale;
|
|
|
|
static std::string get_ctype(typeinfo type, int name = 1, int do_ptr = 1) {
|
|
std::string ret = "";
|
|
|
|
if(type.type == "integer") {
|
|
ret += "int";
|
|
} else if(type.type == "short") {
|
|
ret += "short";
|
|
} else if(type.type == "double") {
|
|
ret += "double";
|
|
} else if(type.type == "string") {
|
|
ret += "MwCXX::String";
|
|
} else if(type.type == "pixmap") {
|
|
ret += "MwLLPixmap";
|
|
} else if(type.type == "pointer") {
|
|
ret += "void*";
|
|
} else if(type.type == "struct") {
|
|
ret += type.struct_name;
|
|
} else if(type.type == "widget") {
|
|
if(type.widget_type == "") {
|
|
ret += "MwCXX::Base*";
|
|
} else {
|
|
ret += "MwCXX::" + type.widget_type + "*";
|
|
}
|
|
} else if(type.type == "class") {
|
|
ret += "MwClass";
|
|
}
|
|
|
|
if(type.unsigned_num) ret = "unsigned " + ret;
|
|
|
|
if(do_ptr && type.pointer) ret += "*";
|
|
|
|
if(name && type.name != "") {
|
|
ret += " " + type.name;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static std::string get_type(typeinfo type) {
|
|
if(type.type == "integer") {
|
|
return "Integer";
|
|
} else if(type.type == "string") {
|
|
return "String";
|
|
}
|
|
|
|
return "Pointer";
|
|
}
|
|
|
|
static std::string uppercase(std::string str) {
|
|
std::string r = str;
|
|
|
|
for(int i = 0; i < r.size(); i++) {
|
|
r[i] = std::toupper(r[i], locale);
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
static std::string lowercase(std::string str) {
|
|
std::string r = str;
|
|
|
|
for(int i = 0; i < r.size(); i++) {
|
|
r[i] = std::tolower(r[i], locale);
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
#define ATTR_TO_BOOL(node, x) ((s = xl_get_attribute(node, (x))) != NULL) && (strcmp(s, "no") != 0);
|
|
|
|
static typeinfo xml_to_type(xl_node_t* node) {
|
|
char* s;
|
|
typeinfo ret;
|
|
|
|
ret.type = node->name;
|
|
ret.name = ((s = xl_get_attribute(node, "name")) != NULL) ? s : "";
|
|
ret.struct_name = ((s = xl_get_attribute(node, "defname")) != NULL) ? s : "";
|
|
ret.widget_type = ((s = xl_get_attribute(node, "type")) != NULL) ? s : "";
|
|
ret.pointer = ATTR_TO_BOOL(node, "pointer");
|
|
ret.unsigned_num = ATTR_TO_BOOL(node, "unsigned");
|
|
|
|
return ret;
|
|
}
|
|
|
|
static std::string upperfirst(std::string str) {
|
|
return uppercase(str.substr(0, 1)) + str.substr(1);
|
|
}
|
|
|
|
static void scan_property(xl_node_t* node) {
|
|
property prop;
|
|
char* s;
|
|
|
|
if(node->type != XL_NODE_NODE) return;
|
|
|
|
prop.type = xml_to_type(node);
|
|
prop.common = ATTR_TO_BOOL(node, "common");
|
|
|
|
props[xl_get_attribute(node, "name")] = prop;
|
|
}
|
|
|
|
static void scan_handler(xl_node_t* node) {
|
|
handler handl;
|
|
char* s;
|
|
xl_node_t* child = node->first_child;
|
|
|
|
if(node->type != XL_NODE_NODE) return;
|
|
|
|
handl.common = ATTR_TO_BOOL(node, "common");
|
|
handl.has_arg = 0;
|
|
|
|
while(child != NULL) {
|
|
if(child->type == XL_NODE_NODE) {
|
|
handl.has_arg = 1;
|
|
handl.arg_type = xml_to_type(child);
|
|
}
|
|
|
|
child = child->next;
|
|
}
|
|
|
|
handlers[xl_get_attribute(node, "name")] = handl;
|
|
}
|
|
|
|
static std::string widget_property_header(std::string name, std::string indent = "") {
|
|
std::stringstream strm;
|
|
|
|
strm << indent + get_ctype(props[name].type, 0) + " Get" + upperfirst(name) + "();" << std::endl;
|
|
strm << indent + "void Set" + upperfirst(name) + "(" + get_ctype(props[name].type, 0) + " value);" << std::endl;
|
|
|
|
return strm.str();
|
|
}
|
|
|
|
static std::string scan_widget_property_header(xl_node_t* node, std::string indent) {
|
|
xl_node_t* child = node->first_child;
|
|
|
|
if(node->type != XL_NODE_NODE) return "";
|
|
|
|
return widget_property_header(xl_get_attribute(node, "name"), indent);
|
|
}
|
|
|
|
static std::string widget_property_source(std::string widget, std::string name) {
|
|
std::stringstream strm;
|
|
|
|
strm << get_ctype(props[name].type, 0) + " MwCXX::" + widget + "::Get" + upperfirst(name) + "() {" << std::endl;
|
|
strm << " return (" + get_ctype(props[name].type, 0) + ")MwGet" + get_type(props[name].type) + "(this->widget, MwN" + name + ");" << std::endl;
|
|
strm << "}" << std::endl;
|
|
strm << std::endl;
|
|
strm << "void MwCXX::" + widget + "::Set" + upperfirst(name) + "(" + get_ctype(props[name].type, 0) + " value) {" << std::endl;
|
|
|
|
if(props[name].type.type == "string") {
|
|
strm << "#ifndef MWCXX_USE_C_STRING" << std::endl;
|
|
strm << " MwSetString(this->widget, MwN" + name + ", value.c_str());" << std::endl;
|
|
strm << "#else" << std::endl;
|
|
}
|
|
|
|
strm << " MwSet" + get_type(props[name].type) + "(this->widget, MwN" + name + ", (" + get_ctype(props[name].type, 0) + ")value);" << std::endl;
|
|
|
|
if(props[name].type.type == "string") {
|
|
strm << "#endif" << std::endl;
|
|
}
|
|
|
|
strm << "}" << std::endl;
|
|
strm << std::endl;
|
|
|
|
return strm.str();
|
|
}
|
|
|
|
static std::string scan_widget_property_source(xl_node_t* node, std::string widget) {
|
|
xl_node_t* child = node->first_child;
|
|
|
|
if(node->type != XL_NODE_NODE) return "";
|
|
|
|
return widget_property_source(widget, xl_get_attribute(node, "name"));
|
|
}
|
|
|
|
static std::string widget_handler_header(std::string widget, std::string name, std::string indent = "", int func = 1) {
|
|
std::stringstream strm;
|
|
std::string pre = "";
|
|
|
|
strm << indent;
|
|
if(func) {
|
|
strm << "virtual void On" + upperfirst(name);
|
|
} else {
|
|
strm << "void (*" + upperfirst(name) + "Handler)";
|
|
|
|
pre += "MwCXX::" + widget + "* widget";
|
|
if(handlers[name].has_arg) pre += ", ";
|
|
}
|
|
|
|
strm << "(" + pre + (handlers[name].has_arg ? (get_ctype(handlers[name].arg_type, 0, 0) + " value") : "") + ")";
|
|
|
|
if(func) strm << " {}";
|
|
|
|
strm << ";" << std::endl;
|
|
|
|
return strm.str();
|
|
}
|
|
|
|
static std::string scan_widget_handler_header(xl_node_t* node, std::string widget, std::string indent, int func = 1) {
|
|
xl_node_t* child = node->first_child;
|
|
|
|
if(node->type != XL_NODE_NODE) return "";
|
|
|
|
return widget_handler_header(widget, xl_get_attribute(node, "name"), indent, func);
|
|
}
|
|
|
|
static std::string widget_handler_source(std::string widget, std::string name) {
|
|
std::stringstream strm;
|
|
std::string cast = "";
|
|
|
|
if(handlers[name].has_arg) {
|
|
cast = "(" + get_ctype(handlers[name].arg_type, 0) + ")";
|
|
|
|
if(handlers[name].arg_type.pointer) cast = "*" + cast;
|
|
|
|
if(handlers[name].arg_type.type == "string") cast += "(char*)";
|
|
|
|
cast += "call";
|
|
}
|
|
|
|
strm << "static void __On" + upperfirst(name) + "(MwWidget handle, void* user, void* call) {" << std::endl;
|
|
strm << " ((MwCXX::" + widget + "*)user)->On" + upperfirst(name) + "(" + cast + ");" << std::endl;
|
|
strm << " if(((MwCXX::" + widget + "*)user)->" + upperfirst(name) + "Handler != NULL) ((MwCXX::" + widget + "*)user)->" + upperfirst(name) + "Handler((MwCXX::" + widget + "*)user" + (handlers[name].has_arg ? (", " + cast) : "") + ");" << std::endl;
|
|
strm << "}" << std::endl;
|
|
strm << std::endl;
|
|
|
|
return strm.str();
|
|
}
|
|
|
|
static std::string scan_widget_handler_source(xl_node_t* node, std::string widget) {
|
|
xl_node_t* child = node->first_child;
|
|
|
|
if(node->type != XL_NODE_NODE) return "";
|
|
|
|
return widget_handler_source(widget, xl_get_attribute(node, "name"));
|
|
}
|
|
|
|
static std::string widget_function_header(xl_node_t* node, std::string indent, std::string prefix = "", int func = 1, xl_node_t** pret = NULL, xl_node_t** pargs = NULL) {
|
|
std::stringstream strm;
|
|
xl_node_t* child;
|
|
xl_node_t* ret = NULL;
|
|
xl_node_t* args = NULL;
|
|
int c = 0;
|
|
|
|
if(node->type != XL_NODE_NODE) return "";
|
|
|
|
for(child = node->first_child; child != NULL; child = child->next) {
|
|
if(child->type != XL_NODE_NODE) continue;
|
|
|
|
if(strcmp(child->name, "return") == 0) {
|
|
for(ret = child->first_child; ret != NULL; ret = ret->next) {
|
|
if(ret->type == XL_NODE_NODE) break;
|
|
}
|
|
} else if(strcmp(child->name, "arguments") == 0) {
|
|
args = child->first_child;
|
|
}
|
|
}
|
|
|
|
if(pret != NULL) *pret = ret;
|
|
if(pargs != NULL) *pargs = args;
|
|
|
|
strm << indent;
|
|
if(ret == NULL) {
|
|
strm << "void ";
|
|
} else {
|
|
strm << get_ctype(xml_to_type(ret)) + " ";
|
|
}
|
|
strm << prefix + std::string(xl_get_attribute(node, "name")) + "(";
|
|
c = 0;
|
|
for(child = args; child != NULL; child = child->next) {
|
|
if(child->type != XL_NODE_NODE) continue;
|
|
|
|
if(c > 0) strm << ", ";
|
|
strm << get_ctype(xml_to_type(child));
|
|
|
|
c++;
|
|
}
|
|
strm << ")";
|
|
if(func) strm << ";";
|
|
strm << std::endl;
|
|
|
|
return strm.str();
|
|
}
|
|
|
|
static std::string widget_function_source(xl_node_t* node, std::string widget) {
|
|
std::stringstream strm;
|
|
xl_node_t* child;
|
|
std::string rettype = "";
|
|
xl_node_t* ret = NULL;
|
|
xl_node_t* args = NULL;
|
|
typeinfo retti;
|
|
|
|
strm << widget_function_header(node, "", "MwCXX::" + widget + "::", 0, &ret, &args) + " {" << std::endl;
|
|
if(ret != NULL) {
|
|
retti = xml_to_type(ret);
|
|
|
|
rettype = get_ctype(retti, 0, 0);
|
|
if(rettype == "MwCXX::String") rettype = "char*";
|
|
|
|
if(retti.pointer) rettype += "*";
|
|
}
|
|
if(rettype != "") {
|
|
strm << " " + rettype + " out;" << std::endl;
|
|
strm << std::endl;
|
|
}
|
|
strm << " MwVaWidgetExecute(this->widget, \"mw" + widget + std::string(xl_get_attribute(node, "name")) + "\", ";
|
|
if(rettype == "") {
|
|
strm << "NULL";
|
|
} else {
|
|
strm << "&out";
|
|
}
|
|
for(child = args; child != NULL; child = child->next) {
|
|
typeinfo ti = xml_to_type(child);
|
|
|
|
if(ti.type == "string") {
|
|
strm << "," << std::endl;
|
|
strm << "#ifdef MWCXX_USE_C_STRING" << std::endl;
|
|
strm << " " + ti.name << std::endl;
|
|
strm << "#else" << std::endl;
|
|
strm << " " + ti.name + ".c_str()" << std::endl;
|
|
strm << "#endif" << std::endl;
|
|
} else {
|
|
strm << ", " + ti.name;
|
|
}
|
|
}
|
|
strm << " );" << std::endl;
|
|
if(rettype != "") {
|
|
strm << std::endl;
|
|
if(retti.type == "string") {
|
|
strm << "#ifdef MWCXX_USE_C_STRING" << std::endl;
|
|
strm << " return out;" << std::endl;
|
|
strm << "#else" << std::endl;
|
|
strm << " return MwCXX::String(out);" << std::endl;
|
|
strm << "#endif" << std::endl;
|
|
} else {
|
|
strm << " return out;" << std::endl;
|
|
}
|
|
}
|
|
strm << "}" << std::endl;
|
|
strm << std::endl;
|
|
|
|
return strm.str();
|
|
}
|
|
|
|
static void scan_widget(xl_node_t* node) {
|
|
std::string name;
|
|
xl_node_t** p_nodes;
|
|
xl_node_t** h_nodes;
|
|
xl_node_t** f_nodes;
|
|
|
|
if(node->type != XL_NODE_NODE) return;
|
|
|
|
p_nodes = xl_get_path(node, "properties");
|
|
h_nodes = xl_get_path(node, "handlers");
|
|
f_nodes = xl_get_path(node, "functions");
|
|
|
|
name = xl_get_attribute(node, "name");
|
|
|
|
#define OFS files["W" + name + ".h"]
|
|
|
|
OFS = std::ofstream("include/MwCXX/Widget/" + name + ".h");
|
|
|
|
OFS << "#ifndef __MWCXX_WIDGET_" + uppercase(name) + "_H__" << std::endl;
|
|
OFS << "#define __MWCXX_WIDGET_" + uppercase(name) + "_H__" << std::endl;
|
|
OFS << std::endl;
|
|
OFS << "#include <MwCXX/MachDep.h>" << std::endl;
|
|
OFS << "#include <MwCXX/Widget/Base.h>" << std::endl;
|
|
OFS << std::endl;
|
|
OFS << "#include <Mw/Widget/" + name + ".h>" << std::endl;
|
|
OFS << std::endl;
|
|
|
|
OFS << "namespace MwCXX {" << std::endl;
|
|
OFS << " class " + name + " : public MwCXX::Base {" << std::endl;
|
|
OFS << " protected:" << std::endl;
|
|
OFS << " virtual void RegisterHandlers();" << std::endl;
|
|
OFS << std::endl;
|
|
OFS << " public:" << std::endl;
|
|
OFS << " " + name + "(MwWidget widget, MwCXX::Base* parent = NULL);" << std::endl;
|
|
OFS << " " + name + "(MwCXX::String name, MwCXX::Base* parent, int x, int y, unsigned int width, unsigned int height);" << std::endl;
|
|
|
|
if(p_nodes != NULL) {
|
|
std::string r;
|
|
|
|
r = "";
|
|
for(int i = 0; p_nodes[i] != NULL; i++) {
|
|
for(xl_node_t* child = p_nodes[i]->first_child; child != NULL; child = child->next) {
|
|
if(child->type != XL_NODE_NODE) continue;
|
|
|
|
r += scan_widget_property_header(child, "\t\t");
|
|
}
|
|
}
|
|
if(r != "") OFS << std::endl
|
|
<< r;
|
|
}
|
|
|
|
if(h_nodes != NULL) {
|
|
std::string r;
|
|
|
|
r = "";
|
|
for(int i = 0; h_nodes[i] != NULL; i++) {
|
|
for(xl_node_t* child = h_nodes[i]->first_child; child != NULL; child = child->next) {
|
|
if(child->type != XL_NODE_NODE) continue;
|
|
|
|
r += scan_widget_handler_header(child, name, "\t\t");
|
|
}
|
|
}
|
|
if(r != "") OFS << std::endl
|
|
<< r;
|
|
|
|
r = "";
|
|
for(int i = 0; h_nodes[i] != NULL; i++) {
|
|
for(xl_node_t* child = h_nodes[i]->first_child; child != NULL; child = child->next) {
|
|
if(child->type != XL_NODE_NODE) continue;
|
|
|
|
r += scan_widget_handler_header(child, name, "\t\t", 0);
|
|
}
|
|
}
|
|
if(r != "") OFS << std::endl
|
|
<< r;
|
|
}
|
|
|
|
if(f_nodes != NULL) {
|
|
std::string r;
|
|
|
|
r = "";
|
|
for(int i = 0; f_nodes[i] != NULL; i++) {
|
|
for(xl_node_t* child = f_nodes[i]->first_child; child != NULL; child = child->next) {
|
|
if(child->type != XL_NODE_NODE) continue;
|
|
|
|
r += widget_function_header(child, "\t\t");
|
|
}
|
|
}
|
|
if(r != "") OFS << std::endl
|
|
<< r;
|
|
}
|
|
|
|
OFS << " };" << std::endl;
|
|
OFS << "}; // namespace MwCXX" << std::endl;
|
|
|
|
OFS << std::endl;
|
|
OFS << "#endif" << std::endl;
|
|
|
|
#undef OFS
|
|
|
|
#define OFS files["W" + name + ".cc"]
|
|
|
|
OFS = std::ofstream("src/widget/" + lowercase(name) + ".cc");
|
|
|
|
if(name == "OpenGL" || name == "Vulkan" || name == "Direct3D9") OFS << "#define MW_" + uppercase(name) + "_NO_INCLUDE" << std::endl;
|
|
|
|
OFS << "#include <MwCXX/Widget/" + name + ".h>" << std::endl;
|
|
OFS << std::endl;
|
|
|
|
OFS << "MwCXX::" + name + "::" + name + "(MwWidget widget, MwCXX::Base* parent) : MwCXX::Base(widget, parent) {" << std::endl;
|
|
OFS << " this->RegisterHandlers();" << std::endl;
|
|
OFS << "}" << std::endl;
|
|
OFS << std::endl;
|
|
|
|
OFS << "MwCXX::" + name + "::" + name + "(MwCXX::String name, MwCXX::Base* parent, int x, int y, unsigned int width, unsigned int height) : MwCXX::Base(Mw" + name + "Class, name, parent, x, y, width, height) {" << std::endl;
|
|
OFS << " this->RegisterHandlers();" << std::endl;
|
|
OFS << "}" << std::endl;
|
|
OFS << std::endl;
|
|
|
|
if(p_nodes != NULL) {
|
|
for(int i = 0; p_nodes[i] != NULL; i++) {
|
|
for(xl_node_t* child = p_nodes[i]->first_child; child != NULL; child = child->next) {
|
|
if(child->type != XL_NODE_NODE) continue;
|
|
|
|
OFS << scan_widget_property_source(child, name);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(h_nodes != NULL) {
|
|
for(int i = 0; h_nodes[i] != NULL; i++) {
|
|
for(xl_node_t* child = h_nodes[i]->first_child; child != NULL; child = child->next) {
|
|
if(child->type != XL_NODE_NODE) continue;
|
|
|
|
OFS << scan_widget_handler_source(child, name);
|
|
}
|
|
}
|
|
}
|
|
|
|
OFS << "void MwCXX::" + name + "::RegisterHandlers() {" << std::endl;
|
|
if(h_nodes != NULL) {
|
|
int f;
|
|
|
|
f = 0;
|
|
for(int i = 0; h_nodes[i] != NULL; i++) {
|
|
for(xl_node_t* child = h_nodes[i]->first_child; child != NULL; child = child->next) {
|
|
std::string hname;
|
|
|
|
if(child->type != XL_NODE_NODE) continue;
|
|
|
|
hname = xl_get_attribute(child, "name");
|
|
|
|
OFS << " MwAddUserHandler(this->widget, MwN" + hname + "Handler, __On" + upperfirst(hname) + ", (void*)this);" << std::endl;
|
|
f = 1;
|
|
}
|
|
}
|
|
|
|
if(f) OFS << std::endl;
|
|
|
|
for(int i = 0; h_nodes[i] != NULL; i++) {
|
|
for(xl_node_t* child = h_nodes[i]->first_child; child != NULL; child = child->next) {
|
|
std::string hname;
|
|
|
|
if(child->type != XL_NODE_NODE) continue;
|
|
|
|
hname = xl_get_attribute(child, "name");
|
|
|
|
OFS << " this->" + upperfirst(hname) + "Handler = NULL;" << std::endl;
|
|
}
|
|
}
|
|
}
|
|
OFS << "}" << std::endl;
|
|
OFS << std::endl;
|
|
|
|
if(f_nodes != NULL) {
|
|
for(int i = 0; f_nodes[i] != NULL; i++) {
|
|
for(xl_node_t* child = f_nodes[i]->first_child; child != NULL; child = child->next) {
|
|
if(child->type != XL_NODE_NODE) continue;
|
|
|
|
OFS << widget_function_source(child, name);
|
|
}
|
|
}
|
|
}
|
|
|
|
#undef OFS
|
|
|
|
if(p_nodes != NULL) free(p_nodes);
|
|
if(h_nodes != NULL) free(h_nodes);
|
|
if(f_nodes != NULL) free(f_nodes);
|
|
|
|
files["objs"] << " src/widget/" + lowercase(name) + ".o";
|
|
}
|
|
|
|
static std::string function_decl(xl_node_t* node, std::string prefix = "") {
|
|
xl_node_t* ret = NULL;
|
|
xl_node_t** nodes;
|
|
std::string r = "";
|
|
|
|
if((nodes = xl_get_path(node, "return")) != NULL) {
|
|
for(int i = 0; nodes[i] != NULL; i++) {
|
|
for(xl_node_t* child = nodes[i]->first_child; child != NULL; child = child->next) {
|
|
if(child->type == XL_NODE_NODE) ret = child;
|
|
}
|
|
}
|
|
|
|
free(nodes);
|
|
}
|
|
|
|
if(ret == NULL) {
|
|
r += "void ";
|
|
} else {
|
|
r += get_ctype(xml_to_type(ret), 0, 0) + " ";
|
|
}
|
|
|
|
r += prefix + std::string(xl_get_attribute(node, "name")).substr(2);
|
|
|
|
r += "(";
|
|
if((nodes = xl_get_path(node, "arguments")) != NULL) {
|
|
for(int i = 0; nodes[i] != NULL; i++) {
|
|
for(xl_node_t* child = nodes[i]->first_child; child != NULL; child = child->next) {
|
|
if(child->type != XL_NODE_NODE) continue;
|
|
|
|
if(r.substr(r.size() - 1, 1) != "(") r += ", ";
|
|
|
|
r += get_ctype(xml_to_type(child), 1, 0);
|
|
}
|
|
}
|
|
|
|
free(nodes);
|
|
}
|
|
r += ")";
|
|
|
|
return r;
|
|
}
|
|
|
|
static std::string function_source(xl_node_t* node) {
|
|
std::stringstream strm;
|
|
xl_node_t** nodes;
|
|
xl_node_t* ret = NULL;
|
|
xl_node_t* widget = NULL;
|
|
typeinfo type;
|
|
int first = 1;
|
|
|
|
if((nodes = xl_get_path(node, "return")) != NULL) {
|
|
for(int i = 0; nodes[i] != NULL; i++) {
|
|
for(xl_node_t* child = nodes[i]->first_child; child != NULL; child = child->next) {
|
|
if(child->type == XL_NODE_NODE) ret = child;
|
|
}
|
|
}
|
|
|
|
free(nodes);
|
|
}
|
|
|
|
strm << function_decl(node, "MwCXX::") << " {" << std::endl;
|
|
|
|
strm << " ";
|
|
if(ret != NULL) {
|
|
type = xml_to_type(ret);
|
|
|
|
if(type.type == "widget") {
|
|
std::string str = get_ctype(type, 0);
|
|
|
|
strm << "return new " + str.substr(0, str.size() - 1) + "(";
|
|
} else {
|
|
strm << "return (" + get_ctype(type, 0) + ")";
|
|
}
|
|
}
|
|
strm << std::string(xl_get_attribute(node, "name")) + "(";
|
|
first = 1;
|
|
if((nodes = xl_get_path(node, "arguments")) != NULL) {
|
|
for(int i = 0; nodes[i] != NULL; i++) {
|
|
for(xl_node_t* child = nodes[i]->first_child; child != NULL; child = child->next) {
|
|
typeinfo type2;
|
|
|
|
if(child->type != XL_NODE_NODE) continue;
|
|
|
|
if(std::string(child->name) == "widget" && widget == NULL) widget = child;
|
|
|
|
type2 = xml_to_type(child);
|
|
|
|
if(first) {
|
|
first = 0;
|
|
} else {
|
|
strm << ", ";
|
|
}
|
|
|
|
if(type2.type == "widget") {
|
|
strm << "(" + type2.name + " == NULL ? NULL : " + type2.name + "->GetWidget())";
|
|
} else {
|
|
if(type2.type == "string") {
|
|
strm << std::endl;
|
|
strm << "#ifdef MWCXX_USE_C_STRING" << std::endl;
|
|
strm << type2.name << std::endl;
|
|
strm << "#else" << std::endl;
|
|
strm << type2.name + ".c_str()" << std::endl;
|
|
strm << "#endif" << std::endl;
|
|
strm << " ";
|
|
} else {
|
|
strm << "(" + get_ctype(type2, 0) + ")" + type2.name;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
free(nodes);
|
|
}
|
|
if(ret != NULL && type.type == "widget") {
|
|
strm << ")";
|
|
if(widget != NULL) strm << ", " + std::string(xl_get_attribute(widget, "name"));
|
|
}
|
|
strm << ");" << std::endl;
|
|
strm << "}" << std::endl;
|
|
|
|
return strm.str();
|
|
}
|
|
|
|
static std::string function_header(xl_node_t* node) {
|
|
return function_decl(node) + ";";
|
|
}
|
|
|
|
static void scan_header(xl_node_t* node) {
|
|
std::string name;
|
|
|
|
if(node->type != XL_NODE_NODE) return;
|
|
|
|
name = xl_get_attribute(node, "name");
|
|
|
|
if(name.size() >= 7 && name.substr(0, 7) == "Dialog/") {
|
|
xl_node_t** nodes;
|
|
|
|
#define OFS files["D" + name.substr(7) + ".h"]
|
|
|
|
OFS = std::ofstream("include/MwCXX/" + name + ".h");
|
|
|
|
OFS << "#ifndef __MWCXX_DIALOG_" + uppercase(name.substr(7)) + "_H__" << std::endl;
|
|
OFS << "#define __MWCXX_DIALOG_" + uppercase(name.substr(7)) + "_H__" << std::endl;
|
|
OFS << std::endl;
|
|
|
|
OFS << "#include <MwCXX/Widget/All.h>" << std::endl;
|
|
OFS << std::endl;
|
|
|
|
OFS << "namespace MwCXX {" << std::endl;
|
|
if((nodes = xl_get_path(node, "functions")) != NULL) {
|
|
for(int i = 0; nodes[i] != NULL; i++) {
|
|
for(xl_node_t* child = nodes[i]->first_child; child != NULL; child = child->next) {
|
|
if(child->type != XL_NODE_NODE) continue;
|
|
|
|
OFS << " " + function_header(child) << std::endl;
|
|
}
|
|
}
|
|
|
|
free(nodes);
|
|
}
|
|
OFS << "}; // namespace MwCXX" << std::endl;
|
|
|
|
OFS << std::endl;
|
|
OFS << "#endif" << std::endl;
|
|
|
|
#undef OFS
|
|
|
|
#define OFS files["D" + name.substr(7) + ".cc"]
|
|
|
|
OFS = std::ofstream("src/dialog/" + lowercase(name.substr(7)) + ".cc");
|
|
|
|
OFS << "#include <MwCXX/" + name + ".h>" << std::endl;
|
|
OFS << std::endl;
|
|
|
|
if((nodes = xl_get_path(node, "functions")) != NULL) {
|
|
for(int i = 0; nodes[i] != NULL; i++) {
|
|
for(xl_node_t* child = nodes[i]->first_child; child != NULL; child = child->next) {
|
|
if(child->type != XL_NODE_NODE) continue;
|
|
|
|
OFS << function_source(child);
|
|
}
|
|
}
|
|
|
|
free(nodes);
|
|
}
|
|
|
|
files["objs"] << " src/dialog/" + lowercase(name.substr(7)) + ".o";
|
|
|
|
#undef OFS
|
|
}
|
|
}
|
|
|
|
static void base_widget() {
|
|
int f;
|
|
|
|
#define OFS files["WBaseAuto.h"]
|
|
|
|
OFS = std::ofstream("include/MwCXX/Widget/BaseAuto.h");
|
|
|
|
f = 0;
|
|
for(auto p = props.begin(); p != props.end(); p++) {
|
|
if(!p->second.common) continue;
|
|
|
|
OFS << widget_property_header(p->first);
|
|
f = 1;
|
|
}
|
|
if(f) OFS << std::endl;
|
|
|
|
f = 0;
|
|
for(auto p = handlers.begin(); p != handlers.end(); p++) {
|
|
if(!p->second.common) continue;
|
|
|
|
OFS << widget_handler_header("Base", p->first);
|
|
f = 1;
|
|
}
|
|
if(f) OFS << std::endl;
|
|
|
|
for(auto p = handlers.begin(); p != handlers.end(); p++) {
|
|
if(!p->second.common) continue;
|
|
|
|
OFS << widget_handler_header("Base", p->first, "", 0);
|
|
}
|
|
|
|
#undef OFS
|
|
|
|
#define OFS files["WBaseAuto.cc"]
|
|
|
|
OFS = std::ofstream("src/widget/baseauto.cc");
|
|
|
|
OFS << "#include <MwCXX/Widget/Base.h>" << std::endl;
|
|
|
|
for(auto p = props.begin(); p != props.end(); p++) {
|
|
if(!p->second.common) continue;
|
|
|
|
OFS << widget_property_source("Base", p->first);
|
|
}
|
|
|
|
for(auto h = handlers.begin(); h != handlers.end(); h++) {
|
|
if(!h->second.common) continue;
|
|
|
|
OFS << widget_handler_source("Base", h->first);
|
|
}
|
|
|
|
OFS << "void MwCXX::Base::RegisterHandlers() {" << std::endl;
|
|
for(auto h = handlers.begin(); h != handlers.end(); h++) {
|
|
if(!h->second.common) continue;
|
|
|
|
OFS << " MwAddUserHandler(this->widget, MwN" + h->first + "Handler, __On" + upperfirst(h->first) + ", (void*)this);" << std::endl;
|
|
}
|
|
OFS << std::endl;
|
|
for(auto h = handlers.begin(); h != handlers.end(); h++) {
|
|
if(!h->second.common) continue;
|
|
|
|
OFS << " this->" + upperfirst(h->first) + "Handler = NULL;" << std::endl;
|
|
}
|
|
OFS << "}" << std::endl;
|
|
|
|
#undef OFS
|
|
|
|
files["objs"] << " src/widget/baseauto.o";
|
|
}
|
|
|
|
int main(int argc, char** argv) {
|
|
xemil_t* h;
|
|
int fail = 0;
|
|
|
|
if(argc < 2) {
|
|
std::cerr << "Usage: " + std::string(argv[0]) + " XML" << std::endl;
|
|
return 1;
|
|
}
|
|
|
|
locale = std::locale::classic();
|
|
|
|
h = xl_open_file(argv[1]);
|
|
|
|
if(h != NULL) {
|
|
h->param.new_text = 1;
|
|
|
|
if(xl_parse(h)) {
|
|
xl_node_t** nodes;
|
|
|
|
files["objs"] = std::ofstream("objs.mk");
|
|
|
|
files["objs"] << "OBJS +=";
|
|
|
|
if((nodes = xl_get_path(h->root, "properties")) != NULL) {
|
|
for(int i = 0; nodes[i] != NULL; i++) {
|
|
for(xl_node_t* child = nodes[i]->first_child; child != NULL; child = child->next) {
|
|
if(child->type != XL_NODE_NODE) continue;
|
|
|
|
scan_property(child);
|
|
}
|
|
}
|
|
|
|
free(nodes);
|
|
}
|
|
|
|
if((nodes = xl_get_path(h->root, "handlers")) != NULL) {
|
|
for(int i = 0; nodes[i] != NULL; i++) {
|
|
for(xl_node_t* child = nodes[i]->first_child; child != NULL; child = child->next) {
|
|
if(child->type != XL_NODE_NODE) continue;
|
|
|
|
scan_handler(child);
|
|
}
|
|
}
|
|
|
|
free(nodes);
|
|
}
|
|
|
|
if((nodes = xl_get_path(h->root, "headers")) != NULL) {
|
|
for(int i = 0; nodes[i] != NULL; i++) {
|
|
for(xl_node_t* child = nodes[i]->first_child; child != NULL; child = child->next) {
|
|
if(child->type != XL_NODE_NODE) continue;
|
|
|
|
scan_header(child);
|
|
}
|
|
}
|
|
|
|
free(nodes);
|
|
}
|
|
|
|
base_widget();
|
|
|
|
#define OFS files["AllWidgets.h"]
|
|
|
|
OFS = std::ofstream("include/MwCXX/Widget/All.h");
|
|
|
|
OFS << "#ifndef __MWCXX_WIDGET_ALL_H__" << std::endl;
|
|
OFS << "#define __MWCXX_WIDGET_ALL_H__" << std::endl;
|
|
OFS << std::endl;
|
|
|
|
if((nodes = xl_get_path(h->root, "widgets")) != NULL) {
|
|
for(int i = 0; nodes[i] != NULL; i++) {
|
|
for(xl_node_t* child = nodes[i]->first_child; child != NULL; child = child->next) {
|
|
std::string name;
|
|
|
|
if(child->type != XL_NODE_NODE) continue;
|
|
|
|
scan_widget(child);
|
|
|
|
name = xl_get_attribute(child, "name");
|
|
|
|
if(name == "OpenGL" || name == "Vulkan" || name == "Direct3D9") continue;
|
|
OFS << "#include <MwCXX/Widget/" + name + ".h>" << std::endl;
|
|
}
|
|
}
|
|
|
|
free(nodes);
|
|
}
|
|
|
|
OFS << std::endl;
|
|
OFS << "#endif" << std::endl;
|
|
|
|
#undef OFS
|
|
|
|
files["objs"] << std::endl;
|
|
|
|
for(auto f = files.begin(); f != files.end(); f++) {
|
|
f->second.close();
|
|
}
|
|
} else {
|
|
fail = 1;
|
|
}
|
|
|
|
xl_close(h);
|
|
} else {
|
|
fail = 1;
|
|
}
|
|
|
|
if(fail) {
|
|
std::cerr << "Failed to parse XML" << std::endl;
|
|
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|