From c8027ebe1d83bd600841e3e4aa183f4aacf46bcb Mon Sep 17 00:00:00 2001 From: aliaspider Date: Sun, 21 Jan 2018 04:28:06 +0100 Subject: [PATCH] (tools) add the tool used to generate the d3d headers. --- {wiiu/slang => deps/peglib}/peglib.h | 24 +- tools/com-parser/Makefile | 160 ++++++ tools/com-parser/com-parse.cpp | 775 +++++++++++++++++++++++++++ tools/com-parser/grammar.txt | 30 ++ wiiu/wiiu_dbg.h | 14 +- 5 files changed, 995 insertions(+), 8 deletions(-) rename {wiiu/slang => deps/peglib}/peglib.h (99%) create mode 100644 tools/com-parser/Makefile create mode 100644 tools/com-parser/com-parse.cpp create mode 100644 tools/com-parser/grammar.txt diff --git a/wiiu/slang/peglib.h b/deps/peglib/peglib.h similarity index 99% rename from wiiu/slang/peglib.h rename to deps/peglib/peglib.h index 20b5080e1b92..d5a5f05321f3 100644 --- a/wiiu/slang/peglib.h +++ b/deps/peglib/peglib.h @@ -1,4 +1,4 @@ -// +// // peglib.h // // Copyright (c) 2015-17 Yuji Hirose. All rights reserved. @@ -2238,6 +2238,20 @@ struct AstBase : public Annotation std::vector>> nodes; std::shared_ptr> parent; + static peg::AstBase empty; + AstBase& operator [] (const char* name) + { + for(std::shared_ptr>& node : nodes) + { + if(node->name == name) + return *node; + } + return empty; + } + operator const char *() + { + return token.c_str(); + } }; template @@ -2770,6 +2784,14 @@ struct peg_token_range { } // namespace peg + +template +std::basic_ios<_Elem, _Traits> &operator << (std::basic_ios<_Elem, _Traits> &ios, + peg::AstBase &node) +{ + return ios << node.token.c_str(); +} + #endif // vim: et ts=4 sw=4 cin cino={1s ff=unix diff --git a/tools/com-parser/Makefile b/tools/com-parser/Makefile new file mode 100644 index 000000000000..71ed3df30300 --- /dev/null +++ b/tools/com-parser/Makefile @@ -0,0 +1,160 @@ + +TARGET = com-parse +DEBUG = 0 +GENDEPS = 1 +TARGET_ARCH = amd64 +OS ?= win32 + + +OBJ := +OBJ += com-parse.o + + + +EXE_EXT := $(suffix $(wildcard $(MAKE).*)) + +ifeq ($(compiler),) + ifeq ($(patsubst %.exe,%,$(basename $(CC))),cl) + compiler = msvc + else + compiler = gcc + endif +endif + +CC_OUT = -o $(NOTHING) +CXX_OUT = $(CC_OUT) +LD_OUT = $(CC_OUT) +OBJ_EXT := o + +ifeq ($(DEBUG),1) + DEFINES += -DDEBUG -D_DEBUG +endif + +ifeq ($(compiler),msvc) + ARCH = amd64 + ARCH2 = x64 + TARGET_ARCH2 = x64 + CROSS = amd64 + WindowsSdkDir = C:\Program Files (x86)\Windows Kits\10\$(NOTHING) + WindowsSDKVersion := 10.0.14393.0\$(NOTHING) + VCINSTALLDIR := C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\$(NOTHING) + + INCLUDE := $(VCINSTALLDIR)include;$(VCINSTALLDIR)atlmfc\include;$(WindowsSdkDir)include\$(WindowsSDKVersion)ucrt;$(WindowsSdkDir)include\$(WindowsSDKVersion)shared;$(WindowsSdkDir)include\$(WindowsSDKVersion)um; + LIB := $(VCINSTALLDIR)LIB\$(CROSS);$(VCINSTALLDIR)atlmfc\lib\$(CROSS);$(WindowsSdkDir)lib\$(WindowsSDKVersion)ucrt\$(TARGET_ARCH2);$(WindowsSdkDir)lib\$(WindowsSDKVersion)um\$(TARGET_ARCH2);C:\Program Files (x86)\NVIDIA Corporation\Cg\lib.$(TARGET_ARCH2);C:\Program Files (x86)\Microsoft DirectX SDK (February 2010)\Lib\$(TARGET_ARCH2); + LIBPATH := $(VCINSTALLDIR)LIB\$(CROSS);$(VCINSTALLDIR)atlmfc\lib\$(CROSS); + + PATH := $(shell IFS=$$'\n'; cygpath "$(VCINSTALLDIR)bin\\$(CROSS)"):$(shell IFS=$$'\n'; cygpath "$(WindowsSdkDir)\bin\\$(ARCH2)"):$(PATH) + + export INCLUDE := $(INCLUDE) + export LIB := $(LIB) + export LIBPATH := $(LIBPATH) + export PATH := $(PATH) + + DEFINES := + FLAGS += -nologo + FLAGS += -Gm- -Zc:inline -fp:precise -Zc:forScope -Gd -Oi -volatile:iso + #FLAGS += -GR- + CFLAGS += -TC + CXXFLAGS += -TP -EHsc + WARNINGS += -WX -W3 + WARNINGS += -wd4101 -wd4996 -wd4244 -wd4267 -wd4090 -wd4305 -wd4146 -wd4334 -wd4018 + + CC = cl.exe + CXX = cl.exe + LD = link.exe + RC = rc.exe + LIBS += shell32.lib user32.lib gdi32.lib comdlg32.lib winmm.lib ole32.lib + LDFLAGS += -nologo -wx -nxcompat -machine:$(TARGET_ARCH2) + ifeq ($(DEBUG),1) + FLAGS += -GS -Gy -Od -RTC1 -D_SECURE_SCL=1 -Zi + FLAGS += -MDd + LDFLAGS += -DEBUG + DEFINES += -DDEBUG -D_DEBUG + else + FLAGS += -GS- -Gy- -O2 -Ob2 -GF -GT -Oy -Ot -D_SECURE_SCL=0 + FLAGS += -MD + endif + OBJ := $(OBJ:.o=.obj) + LDFLAGS += -WX -SUBSYSTEM:WINDOWS -ENTRY:mainCRTStartup + DEFINES := $(patsubst -f%,,$(DEFINES)) + LDFLAGS := $(patsubst -l%,%.lib,$(LDFLAGS)) + LIBS := $(filter-out -lm,$(LIBS)) + LIBS := $(patsubst -l%,%.lib,$(LIBS)) + DEPFLAGS = -showIncludes | tee $*.dtemp | sed /'Note: including file:'/d + MAKEDEPS = echo $@: $< \\ > $*.depend && \ + grep 'Note: including file:' $*.dtemp \ + | sed '/$(subst \,\\,$(WindowsSdkDir))/Id; /$(subst \,\\,$(VCINSTALLDIR))/Id; s/Note: including file:[ ]*//g; s/\\/\//g; s/ /\\ /g; s/.*/ & \\/g' \ + >> $*.depend && \ + rm -f $*.dtemp + + OBJ_EXT := obj + CC_OUT := -Fo: + CXX_OUT := $(CC_OUT) + LD_OUT := -out: +else + RC := windres + DEPFLAGS = -MT $@ -MMD -MP -MF $(BUILD_DIR)$*.depend + LD = $(CXX) + ifeq ($(DEBUG),1) + FLAGS += -g -O0 + else + FLAGS += -O3 + endif +endif + + +INCLUDE_DIRS += -I. -I../../deps/peglib + + +$(info os : $(OS)) +$(info host : $(ARCH)) +$(info target : $(TARGET_ARCH)) +$(info compiler : $(compiler)) + +all: $(TARGET)$(EXE_EXT) + +%.h: + touch $*.tmp + $(CXX) $*.tmp -DCINTERFACE -D_REFIID_DEFINED= -D_REFGUID_DEFINED= -D_HRESULT_DEFINED= \ + -EP -FI $@ $(FLAGS) $(CXXFLAGS) $(DEFINES) $(INCLUDE_DIRS) $(WARNINGS) > $@ + rm $*.tmp + +SHELL:=$(SHELL) -o pipefail + + +ifeq ($(GENDEPS),0) + DEPFLAGS := + MAKEDEPS := +endif + +%.$(OBJ_EXT): %.cpp + $(CXX) -c $(CXX_OUT)$@ $< $(FLAGS) $(CXXFLAGS) $(DEFINES) $(INCLUDE_DIRS) $(WARNINGS) $(DEPFLAGS) + @$(MAKEDEPS) + +%.$(OBJ_EXT): %.c + $(CC) -c $(CC_OUT)$@ $< $(FLAGS) $(CFLAGS) $(DEFINES) $(INCLUDE_DIRS) $(WARNINGS) $(DEPFLAGS) + @$(MAKEDEPS) + +%.res: %.rc + $(RC) $< + mv $*.res $@ + +$(TARGET)$(EXE_EXT): $(OBJ) .$(TARGET).last + @touch .$(TARGET).last + $(LD) $(OBJ) $(LDFLAGS) $(LIBS) $(LD_OUT)$@ + + +%.depend: ; +%.last: ; +.FORCE: + +clean: + rm -f $(OBJ) $(TARGET)$(EXE_EXT) + rm -f $(TARGET) + rm -f .$(TARGET).last + rm -f $(OBJ:.obj=.depend) + +.PHONY: clean all +.PRECIOUS: %.depend %.last + +-include $(patsubst %.obj,%.depend,$(filter %.obj,$(OBJ))) diff --git a/tools/com-parser/com-parse.cpp b/tools/com-parser/com-parse.cpp new file mode 100644 index 000000000000..229be04e8911 --- /dev/null +++ b/tools/com-parser/com-parse.cpp @@ -0,0 +1,775 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2014-2018 - Ali Bouhlel + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + + +#include +#include +#include +#include +#include + +using namespace peg; +using namespace std; + +template +AstBase AstBase::empty = AstBase("", 0, 0, "", string("")); + + +//bool use_typedefs = false; +bool use_typedefs = true; + +//const char* prefix_seperator = "_"; +const char* prefix_seperator = ""; + +vector ignored_fn_prefixes_list = +{ + "OM", + "IA", + "RS", +}; + +vector fn_prefixes_list = +{ + "OM", + "IA", + "RS", + "VS", + "PS", + "GS", + "DS", + "CS", +}; + +bool move_fn_prefix_after_action = true; + +vector ignored_types_list = +{ + "AsyncIUnknown", + "IMarshal", + "IMalloc", + "IEnumString", + "ISequentialStream", + "IStream", + "IRpcChannelBuffer", + "IAsyncRpcChannelBuffer", + "IRpcProxyBuffer", + "IServerSecurity", + "IRpcOptions", + "IGlobalOptions", + "ISurrogate", + "ISynchronize", + "ISynchronizeEvent", + "IDataObject", + "IDataAdviseHolder", + "IDirectWriterLock", + "IDummyHICONIncluder", + "IDispatch", + "IDropSource", + "IDropTarget", + "IDataFilter", + "IDropSourceNotify", +}; + +const char* required_prefix = "ID"; + +vector ignored_functions_list = +{ + "Release", + "QueryInterface", + "AddRef", + "GetParent", + "GetAdapter", + "GetDevice", + "GetDesc", + "GetType", + "SetName", + "SetPrivateDataInterface", + "SetPrivateData", + "GetPrivateData", + + "OpenSharedHandle", + "CreateSharedHandle", + "OpenSharedHandleByName", + + "SetTrackingOptions", +}; + +vector overloaded_list = +{ + "Release", + "QueryInterface", + "AddRef", + "GetParent", + "GetAdapter", + "GetDesc", + "GetType", + "SetName", + "SetPrivateDataInterface", + "SetPrivateData", + "GetPrivateData", + "Reset", + "Signal", + "BeginEvent", + "EndEvent", + "SetMarker", + "AssertResourceState", + "GetFeatureMask", + "SetFeatureMask", + "GetFrameStatistics", + "Close", + "SetEvictionPriority", + "GetEvictionPriority", + "GetResource", + "GetDataSize", + "GetContextFlags", + "GetCertificate", + "GetCertificateSize", +}; + +vector action_list = +{ + "Release", + "Get", + "Set", + "Enum", + "Get", + "Query", + "Add", + "Signal", + "Begin", + "End", + "Assert", + "Close", + "Map", + "Unmap" +}; + +vector derived_types_list = +{ + "ID3D12Device", + "ID3D12Debug", + "ID3D12DebugDevice", + "ID3D12DebugCommandList", + "IDXGIFactory1", + "IDXGIAdapter1", + "IDXGISurface1", + "IDXGISwapChain3", + "IDXGIOutput", + "IDXGIDevice", +}; + +vector base_objects_list = +{ + "IUnknown", + "ID3D12Object", + "ID3D12Resource", + "IDXGIObject", + "IDXGIResource", + "D3D11Resource", +}; + +//string insert_name(const char* fname, const char* name) +string insert_name(const string& fname, const string& name) +{ + string str; + for(string action: action_list) + { + if(!strncmp(fname.c_str(), action.c_str(), action.length())) + { + if(name.length() == 2 && name[1] == 'S') + { + if(!strncmp(fname.c_str() + action.length(), "Shader", strlen("Shader"))) + return action + name[0] + (fname.c_str() + action.length()); + else + return action + name[0] + "Shader" + (fname.c_str() + action.length()); + } + else + return action + name + (fname.c_str() + action.length()); + } + } + return string(fname) + name; + +} +//string insert_name(string fname, string name) +//{ +// return insert_name(fname.c_str(), name.c_str()); +//} + +string get_derived_basename(const char *name) +{ + string str = name; + if(::isdigit(str.back())) + str.pop_back(); + + return str; +} + +string get_derived_basename(string name) +{ + return get_derived_basename(name.c_str()); +} + +string get_prefix(const char *type) +{ + string prefix; + + if(*type != 'I') + return type; + + type++; + + while (::isalnum(*type) && !::islower(*type)) + prefix.push_back(*type++); + + prefix.pop_back(); + + return prefix; +} + +string get_prefix(const string &type) +{ + return get_prefix(type.c_str()); +} + + +string clean_name(const char *name) +{ + string str; + + if (name[0] == 'p' && name[1] == 'p' && name[2] == 'v' && ::isupper(name[3])) + name += 3; + if (name[0] == 'p' && name[1] == 'p' && ::isupper(name[2])) + name += 2; + else if ((*name == 'p' || *name == 'b') && ::isupper(name[1])) + name ++; + + bool was_upper = false; + if (*name) + { + if (::isupper(*name)) + { + was_upper = true; + str = (char)::tolower(*name); + } + else + str = *name; + } + + while (*++name) + { + if (::isupper(*name)) + { + if(!was_upper && !::isdigit(str.back())) + str = str + '_'; + + was_upper = true; + str += (char)::tolower(*name); + } + else + { + was_upper = false; + str += *name; + } + } + + if(str == "enum") + str = "enumerator"; + + return str; +} + +struct name_pair{ + string name; + string original; +}; + +class ComFunction +{ +public: + struct param_t + { + name_pair type; + name_pair ptr; + name_pair name; + int array_size = 0; + bool const_ = false; + bool base = false; + bool derived = false; + }; + param_t this_; + vector params; + string riid; + + string name; + string original_name; + string return_type; + string prefix; + + bool overloaded = false; + bool ignored = false; + bool preferred = false; + + ComFunction(Ast node) + { + original_name = node["FunctionName"]; + return_type = node["ReturnType"]; + + for (auto param_ : node["Parameters"].nodes) + { + Ast ¶m = *param_; + param_t p; + p.type.original = param["Type"]["Name"]; + p.const_ = param["Type"]["TypeQualifier"] == "const"; + + if(p.type.original == "REFIID") + { + riid = string("I") + prefix; + continue; + } + if(!riid.empty()) + { + if(param["Name"][2] == 'v') + riid += param["Name"] + 3; + else + riid += param["Name"] + 2; + break; + } + + p.ptr.original = param["Type"]["Pointer"]; + p.ptr.name = p.ptr.original; + + if(use_typedefs && + (prefix.empty() || (p.type.original[0] == 'I' && !strncmp(p.type.original.c_str() + 1, prefix.c_str(), prefix.length()))) + ) + { + p.type.name = p.type.original.c_str() + 1; + if(::isdigit(p.type.name.back())) + p.type.name.pop_back(); + + if(!p.ptr.name.empty()) + p.ptr.name.pop_back(); + } + else + { + p.type.name = p.type.original; + p.ptr.name = p.ptr.name; + } + + if (param.name == "This") + { + prefix = get_prefix(p.type.original); + p.name.original = param["Type"]["Name"] + 1 + prefix.length(); + p.name.name = clean_name(p.name.original.c_str()); + if(::isdigit(p.name.name.back())) + p.name.name.pop_back(); + + this_ = p; + } + else + { + p.name.original = param["Name"]; + p.name.name = clean_name(p.name.original.c_str()); + p.array_size = ::strtoul(param["ArraySize"], NULL, 10); + params.push_back(p); + } + + } + + if(original_name == "GetCPUDescriptorHandleForHeapStart") + { + param_t p; + p.type.name = p.type.original = return_type; + p.ptr.name = p.ptr.original = "*"; + return_type = "void"; + p.name.name = p.name.original = "out"; + params.push_back(p); + } + + for(string str : ignored_functions_list) + if(original_name == str) + ignored = true; + + for(string str : ignored_types_list) + if(get_derived_basename(this_.type.original) == get_derived_basename(str)) + ignored = true; + + if(required_prefix) + if(strncmp(this_.type.original.c_str(), required_prefix, strlen(required_prefix))) + ignored = true; + + for(string str : derived_types_list) + { + if(get_derived_basename(this_.type.original) == get_derived_basename(str)) + { + this_.derived = true; + if(this_.type.original != str) + ignored = true; + } + for (param_t ¶m : params) + if(get_derived_basename(param.type.original) == get_derived_basename(str)) + { + if(param.type.original != str) + param.derived = true; + else + { +// cout << param.type.original << endl; + preferred = true; + } + } + } + + for(string str : overloaded_list) + if(original_name == str) + overloaded = true; + + for(string str : base_objects_list) + { + if(this_.type.original == str) + this_.base = true; + for (param_t ¶m : params) + if(param.type.original == str) + param.base = true; + + } + + name = prefix + prefix_seperator; + + if(overloaded && !this_.base) + { + name += insert_name(original_name, this_.name.original); + if(::isdigit(name.back())) + name.pop_back(); + } + else + { + string fn_prefix; + for (string& str : ignored_fn_prefixes_list) + if(!strncmp(original_name.c_str(), str.c_str(), str.length())) + { + if(::isupper(original_name[str.length()])) + fn_prefix = str; + break; + } + if(!fn_prefix.empty()) + { + name += original_name.c_str() + fn_prefix.length(); + } + else + { + for (string str : fn_prefixes_list) + if(!strncmp(original_name.c_str(), str.c_str(), str.length())) + { + if(::isupper(original_name[str.length()])) + fn_prefix = str; + break; + } + if(!fn_prefix.empty()) + name += insert_name(original_name.c_str() + fn_prefix.length(), fn_prefix.c_str()); + else + name += original_name; + } + } + +// if(original_name == "CreateCommandQueue" && ignored) +// cout << "ignored CreateCommandQueue !!" << __LINE__ << endl; + + } + string str() + { + stringstream out; + out << "static inline " << return_type << " " << name << "("; + + if(this_.base) + out << "void*"; + else + out << this_.type.name << this_.ptr.name; + + out << " " << this_.name.name; + + for (param_t ¶m : params) + { + out << ", "; + + if(param.const_) + out << "const "; + + if(param.base) + out << "void*"; + else + out << param.type.name << param.ptr.name; + + out << " " << param.name.name; + if(param.array_size) + out << '[' << param.array_size << ']'; + + } + if(!riid.empty()) + out << ", " << riid << "** out"; + + out << ")\n{\n"; + out << " "; + + if (return_type != "void") + out << "return "; + + if(original_name == "GetCPUDescriptorHandleForHeapStart") + out << "((void (STDMETHODCALLTYPE *)(ID3D12DescriptorHeap*, D3D12_CPU_DESCRIPTOR_HANDLE*))\n "; + + if(this_.base) + out << "((" << this_.type.original << this_.ptr.original << ')' << this_.name.name << ')'; + else + out << this_.name.name; + + out << "->lpVtbl->" << original_name; + + if(original_name == "GetCPUDescriptorHandleForHeapStart") + out << ')'; + + out << '(' << this_.name.name; + + for (param_t param : params) + { + out << ", "; + + if(param.base || param.derived) + out << '(' << param.type.original << param.ptr.original << ')'; + + out << param.name.name; + } + + if(!riid.empty()) + out << ", __uuidof(" << riid << "), (void**)out"; + + out << ");\n"; + out << "}\n"; + return out.str(); + } + + +}; +class ComHeader +{ +public: + shared_ptr ast; + vector functions; + vector types; + ComHeader(const char *filename) + { + string header; + { + ifstream fs(filename); +#if 0 + stringstream ss; + ss << fs.rdbuf(); + header = ss.str(); +#else + while (!fs.eof()) + { + char line[4096]; + fs.getline(line, sizeof(line)); + char* str = line; + while (*str && ::isspace(*str)) + str++; + if (*str && !strncmp(str, "typedef struct ", strlen("typedef struct "))) + { + if(*str && strstr(str, "Vtbl")) + { + header += str; + header.push_back('\n'); + while(*line) + { + fs.getline(line, sizeof(line)); + str = line; + while (*str && ::isspace(*str)) + str++; + if(*str) + { + header += str; + header.push_back('\n'); + } + if(*str == '}') + break; + } + } + } + } +#endif + } + { + ofstream out("test.cpp.h"); + out << header; + out.close(); + } + + string header_grammar; + { + ifstream fs("grammar.txt"); + stringstream ss; + ss << fs.rdbuf(); + header_grammar = ss.str(); + } + + parser parser; + parser.log = [&](size_t ln, size_t col, const string & msg) + { + cout << "Error parsing grammar:" << ln << ":" << col << ": " << msg << endl; + }; + + if (!parser.load_grammar(header_grammar.c_str())) + { + cout << "Failed to load grammar" << endl; + return; + } + + parser.log = [&](size_t ln, size_t col, const string & msg) + { + cout << filename << ":" << ln << ":" << col << ": " << msg << endl; + }; + + parser.enable_ast(); + + if (!parser.parse_n(header.c_str(), header.size(), ast)) + { + cout << "Error parsing header file: " << filename << endl; + return; + } + + ast = AstOptimizer(false).optimize(ast); + + if (ast->name != "Program") + { + cout << "Expected root node to be Program, not" << ast->name << endl; + return; + } + + for (shared_ptr node_ : ast->nodes) + { + Ast node = *node_; + + if (node.name == "Function") + functions.push_back(node); + else if (node.name == "Line") + { + + } + else if (node.name == "EndOfFile") + break; + else + { +// cout << "Unexcpected node " << node->name << endl; + } + } + + for(ComFunction& fn : functions) + { + if(!fn.ignored && fn.preferred && ::isdigit(fn.name.back())) + { + fn.name.pop_back(); + for(ComFunction& fn2 : functions) + if(&fn != &fn2 && !fn2.ignored && get_derived_basename(fn.original_name) == get_derived_basename(fn2.original_name)) + { +// cout << &fn << &fn2 << fn.original_name << " " << fn2.original_name << endl; +// assert(fn2.preferred == false); + fn2.ignored = true; +// if(fn2.original_name == "CreateCommandQueue" && fn2.ignored) +// cout << "ignored CreateCommandQueue !!" << __LINE__ << endl; + } + } + } + + for(ComFunction& fn : functions) + { + if(!fn.ignored) + { + bool known = false; + for(name_pair& known_type:types) + if (fn.this_.type.original == known_type.original) + { + known = true; + break; + } + + if(!known) + types.push_back(fn.this_.type); + } + } + } + ComHeader(shared_ptr ast_) + { + + } + string str() + { + stringstream out; + int indent = 0; + for(name_pair known_type:types) + if (indent < known_type.original.length()) + indent = known_type.original.length(); + + for(name_pair known_type:types) + { + out << "typedef " << known_type.original << '*' << string(indent + 1 - known_type.original.length(), ' ') << known_type.name << ";\n"; + } + out << "\n\n"; + for (ComFunction &fn : functions) + if(!fn.ignored) + out << fn.str(); + return out.str(); + } + +}; + +template +basic_ostream<_Elem, _Traits> &operator << (basic_ostream<_Elem, _Traits> &ios, ComHeader &header) +{ + return ios << header.str(); +} + + +int main(int argc, const char **argv) +{ + const char *header_fn = argv[1]; + ComHeader header(header_fn); + + if (header.functions.empty()) + return 1; + + if (argc > 2) + cout << ast_to_s(header.ast) << flush; + + ofstream out("test.h"); + const char* basename = strrchr(argv[1], '/'); + if(!basename) + basename = strrchr(argv[1], '\\'); + if(basename) + basename++; + if(!basename) + basename = argv[1]; + +#if 1 + out << "\n#include <" << basename << ">\n\n"; +#else + out << "\n"; + out << "#include \n"; + out << "#include \n"; + out << "#include \n\n"; +#endif + + out << header; + out.close(); + + + return 0; +} diff --git a/tools/com-parser/grammar.txt b/tools/com-parser/grammar.txt new file mode 100644 index 000000000000..21cf85f57dad --- /dev/null +++ b/tools/com-parser/grammar.txt @@ -0,0 +1,30 @@ + +Program <- (Function / Comment / Line)* EndOfFile + + +Function <- _ ReturnType _ '(' _ FunctionName _ ')'_ Parameters +Parameters <- '('_ This _ ','? _ ( _ Param _ ','?)*_ ');' +FunctionName <- CallType _ '*' _ +This <- Type _ 'This' +Param <- InOut? _ Type _ Name _ ArraySize? +ReturnType <- +Type <- (TypeQualifier _)? Name Pointer? +TypeQualifier <- 'const' +~CallType <- '__export'? ('STDMETHODCALLTYPE' / 'STDMETHODVCALLTYPE' / 'STDAPICALLTYPE' / 'STDAPIVCALLTYPE' / '__cdecl' / '__stdcall') +~InOut <- '_'Name + +ArraySize <- '[' _ _ ']' +Pointer <- _<('*'/'const '/'const')+> +Name <- <([a-z]/[A-Z]/'_'/[0-9])+> +Number <- <[0-9]+> +~Line <- <(!EndOfLine !EndOfFile .)*> (EndOfLine / EndOfFile) + +~EndOfStatement <- ';' +~EndOfLine <- '\r\n' / '\n' / '\r' +EndOfFile <- !. +End <- EndOfLine / EndOfFile +~_ <- (Comment / [ \t\r\n])* +Indent <- [ \t] +~Space <- [ \t] +Comment <- [ \t]*<('/*' (!'*/' .)* '*/' / '//') Line> + diff --git a/wiiu/wiiu_dbg.h b/wiiu/wiiu_dbg.h index b75edfaf2722..5e2270148408 100644 --- a/wiiu/wiiu_dbg.h +++ b/wiiu/wiiu_dbg.h @@ -26,13 +26,13 @@ void DisassemblePPCRange(void *start, void *end, void* printf_func, void* GetSym /* #define DEBUG_HOLD() do{printf("%s@%s:%d.\n",__FUNCTION__, __FILE__, __LINE__);fflush(stdout);wait_for_input();}while(0) */ #define DEBUG_LINE() do{printf("%s:%4d %s().\n", __FILE__, __LINE__, __FUNCTION__);fflush(stdout);}while(0) -#define DEBUG_STR(X) printf( "%s: %s\n", #X, (char*)(X)) -#define DEBUG_VAR(X) printf( "%-20s: 0x%08" PRIX32 "\n", #X, (uint32_t)(X)) -#define DEBUG_VAR2(X) printf( "%-20s: 0x%08" PRIX32 " (%i)\n", #X, (uint32_t)(X), (int)(X)) -#define DEBUG_INT(X) printf( "%-20s: %10" PRIi32 "\n", #X, (int32_t)(X)) -#define DEBUG_FLOAT(X) printf( "%-20s: %10.3f\n", #X, (float)(X)) -#define DEBUG_VAR64(X) printf( #X"\r\t\t\t\t : 0x%016" PRIX64 "\n", (uint64_t)(X)) -#define DEBUG_MAGIC(X) printf( "%-20s: '%c''%c''%c''%c' (0x%08X)\n", #X, (u32)(X)>>24, (u32)(X)>>16, (u32)(X)>>8, (u32)(X),(u32)(X)) +#define DEBUG_STR(X) do{printf( "%s: %s\n", #X, (char*)(X));fflush(stdout);}while(0) +#define DEBUG_VAR(X) do{printf( "%-20s: 0x%08" PRIX32 "\n", #X, (uint32_t)(X));fflush(stdout);}while(0) +#define DEBUG_VAR2(X) do{printf( "%-20s: 0x%08" PRIX32 " (%i)\n", #X, (uint32_t)(X), (int)(X));fflush(stdout);}while(0) +#define DEBUG_INT(X) do{printf( "%-20s: %10" PRIi32 "\n", #X, (int32_t)(X));fflush(stdout);}while(0) +#define DEBUG_FLOAT(X) do{printf( "%-20s: %10.3f\n", #X, (float)(X));fflush(stdout);}while(0) +#define DEBUG_VAR64(X) do{printf( "%-20s: 0x%016" PRIX64 "\n", #X, (uint64_t)(X));fflush(stdout);}while(0) +#define DEBUG_MAGIC(X) do{printf( "%-20s: '%c''%c''%c''%c' (0x%08X)\n", #X, (u32)(X)>>24, (u32)(X)>>16, (u32)(X)>>8, (u32)(X),(u32)(X));fflush(stdout);}while(0) /* #define DEBUG_ERROR(X) do{if(X)dump_result_value(X);}while(0) */ #define PRINTFPOS(X,Y) "\x1b["#X";"#Y"H"