mirror of
https://github.com/ptitSeb/box64.git
synced 2026-11-07 09:26:11 -10:00
Added a useful script
This commit is contained in:
1 parent
1f02ab17e3
commit
f014d4580a
4 files changed
+742
No files matched your search
@@ -59,3 +59,8 @@ build*/
|
||||
src/git_head.h
|
||||
backup/
|
||||
|
||||
# LLVMprivateGenerator
|
||||
/LLVMprivateGenerator/*
|
||||
!/LLVMprivateGenerator/Makefile
|
||||
!/LLVMprivateGenerator/main.cpp
|
||||
!/LLVMprivateGenerator/registered_structs.cpp
|
||||
@@ -0,0 +1,12 @@
|
||||
all: dumpSigs
|
||||
|
||||
dumpSigs: main.o registered_structs.o
|
||||
g++ -g3 -std=gnu++17 -fno-rtti main.o registered_structs.o -o dumpSigs "-L$(LLVM_install_dir)/lib" -lclang-cpp -lclangTooling -Wl,-rpath "-Wl,$(LLVM_install_dir)/lib"
|
||||
|
||||
main.o: main.cpp
|
||||
g++ -g3 -std=gnu++17 -fno-rtti -c main.cpp -Wfatal-errors "-I$(LLVM_install_dir)/include" -o main.o
|
||||
registered_structs.o: registered_structs.cpp
|
||||
g++ -g3 -std=gnu++17 -fno-rtti -c registered_structs.cpp -Wfatal-errors -o registered_structs.o
|
||||
|
||||
clean:
|
||||
$(RM) dumpSigs main.o registered_structs.o
|
||||
@@ -0,0 +1,458 @@
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <numeric>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <llvm/Support/raw_ostream.h>
|
||||
#include <clang/AST/ASTConsumer.h>
|
||||
#include <clang/AST/Decl.h>
|
||||
#include <clang/AST/Mangle.h>
|
||||
#include <clang/AST/PrettyPrinter.h>
|
||||
#include <clang/AST/RecursiveASTVisitor.h>
|
||||
#include <clang/Frontend/CompilerInstance.h>
|
||||
#include <clang/Frontend/FrontendActions.h>
|
||||
#include <clang/Tooling/CommonOptionsParser.h>
|
||||
#include <clang/Tooling/Tooling.h>
|
||||
|
||||
clang::MangleContext *mangler = nullptr;
|
||||
|
||||
std::unordered_map<std::string, std::pair<std::string, bool>> funMap;
|
||||
std::vector<std::string> funList;
|
||||
|
||||
bool isTypeTrivial(const clang::QualType &q, const clang::QualType *qorig);
|
||||
clang::QualType getPointedType(const clang::QualType q) {
|
||||
if (const clang::PointerType *p = q->getAs<clang::PointerType>())
|
||||
return getPointedType(p->getPointeeType());
|
||||
else if (const clang::ReferenceType *r = q->getAs<clang::ReferenceType>())
|
||||
return getPointedType(r->getPointeeType());
|
||||
else
|
||||
return q;
|
||||
}
|
||||
|
||||
std::string record2name(const clang::RecordDecl &q, const clang::QualType *qorig) {
|
||||
std::string s = q.getNameAsString();
|
||||
if (s == "") {
|
||||
if (!qorig) return "????.!";
|
||||
if (const clang::TypedefType *tt = (*qorig)->getAs<clang::TypedefType>()) {
|
||||
// Typedef
|
||||
if (clang::TypedefNameDecl *td = tt->getDecl()) {
|
||||
return td->getNameAsString();
|
||||
} else {
|
||||
return "<typedef with no declaration>";
|
||||
}
|
||||
} else {
|
||||
return std::string("<unknown type ") + (*qorig)->getTypeClassName() + ">";
|
||||
}
|
||||
} else {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
char ptr2char(const std::string &str) __attribute__((const));
|
||||
const char *ptr2str(const std::string &str) __attribute__((const));
|
||||
char type2char(const clang::QualType &qual /* Canonical */, const clang::QualType *qorig) {
|
||||
if (qual->isBuiltinType()) {
|
||||
switch (static_cast<const clang::BuiltinType&>(*qual).getKind()) {
|
||||
case clang::BuiltinType::Kind::Void:
|
||||
return 'v';
|
||||
case clang::BuiltinType::Kind::Bool:
|
||||
return 'i';
|
||||
case clang::BuiltinType::Kind::Char_U:
|
||||
return 'C';
|
||||
case clang::BuiltinType::Kind::Char_S:
|
||||
return 'c';
|
||||
case clang::BuiltinType::Kind::Char8:
|
||||
return 'c';
|
||||
case clang::BuiltinType::Kind::UChar:
|
||||
return 'C';
|
||||
case clang::BuiltinType::Kind::SChar:
|
||||
return 'c';
|
||||
case clang::BuiltinType::Kind::WChar_U:
|
||||
return 'W';
|
||||
case clang::BuiltinType::Kind::UShort:
|
||||
return 'W';
|
||||
case clang::BuiltinType::Kind::WChar_S:
|
||||
return 'w';
|
||||
case clang::BuiltinType::Kind::Char16:
|
||||
return 'w';
|
||||
case clang::BuiltinType::Kind::Short:
|
||||
return 'w';
|
||||
case clang::BuiltinType::Kind::UInt:
|
||||
return 'u';
|
||||
case clang::BuiltinType::Kind::Char32:
|
||||
return 'i';
|
||||
case clang::BuiltinType::Kind::Int:
|
||||
return 'i';
|
||||
case clang::BuiltinType::Kind::ULong:
|
||||
return 'L';
|
||||
case clang::BuiltinType::Kind::Long:
|
||||
return 'l';
|
||||
case clang::BuiltinType::Kind::ULongLong:
|
||||
return 'U';
|
||||
case clang::BuiltinType::Kind::LongLong:
|
||||
return 'I';
|
||||
case clang::BuiltinType::Kind::UInt128:
|
||||
return 'H';
|
||||
case clang::BuiltinType::Kind::Int128:
|
||||
return 'H';
|
||||
case clang::BuiltinType::Kind::Float:
|
||||
return 'f';
|
||||
case clang::BuiltinType::Kind::Double:
|
||||
return 'd';
|
||||
case clang::BuiltinType::Kind::LongDouble:
|
||||
return 'D';
|
||||
case clang::BuiltinType::Kind::NullPtr:
|
||||
return 'p'; // nullptr_t
|
||||
|
||||
case clang::BuiltinType::Kind::Half:
|
||||
case clang::BuiltinType::Kind::BFloat16:
|
||||
case clang::BuiltinType::Kind::ShortAccum:
|
||||
case clang::BuiltinType::Kind::Accum:
|
||||
case clang::BuiltinType::Kind::LongAccum:
|
||||
case clang::BuiltinType::Kind::UShortAccum:
|
||||
case clang::BuiltinType::Kind::UAccum:
|
||||
case clang::BuiltinType::Kind::ULongAccum:
|
||||
case clang::BuiltinType::Kind::ShortFract:
|
||||
case clang::BuiltinType::Kind::Fract:
|
||||
case clang::BuiltinType::Kind::LongFract:
|
||||
case clang::BuiltinType::Kind::UShortFract:
|
||||
case clang::BuiltinType::Kind::UFract:
|
||||
case clang::BuiltinType::Kind::ULongFract:
|
||||
case clang::BuiltinType::Kind::SatShortAccum:
|
||||
case clang::BuiltinType::Kind::SatAccum:
|
||||
case clang::BuiltinType::Kind::SatLongAccum:
|
||||
case clang::BuiltinType::Kind::SatUShortAccum:
|
||||
case clang::BuiltinType::Kind::SatUAccum:
|
||||
case clang::BuiltinType::Kind::SatULongAccum:
|
||||
case clang::BuiltinType::Kind::SatShortFract:
|
||||
case clang::BuiltinType::Kind::SatFract:
|
||||
case clang::BuiltinType::Kind::SatLongFract:
|
||||
case clang::BuiltinType::Kind::SatUShortFract:
|
||||
case clang::BuiltinType::Kind::SatUFract:
|
||||
case clang::BuiltinType::Kind::SatULongFract:
|
||||
case clang::BuiltinType::Kind::Float16:
|
||||
case clang::BuiltinType::Kind::Float128:
|
||||
case clang::BuiltinType::Kind::Overload:
|
||||
case clang::BuiltinType::Kind::BoundMember:
|
||||
case clang::BuiltinType::Kind::PseudoObject:
|
||||
case clang::BuiltinType::Kind::Dependent:
|
||||
case clang::BuiltinType::Kind::UnknownAny:
|
||||
case clang::BuiltinType::Kind::ARCUnbridgedCast:
|
||||
case clang::BuiltinType::Kind::BuiltinFn:
|
||||
case clang::BuiltinType::Kind::ObjCId:
|
||||
case clang::BuiltinType::Kind::ObjCClass:
|
||||
case clang::BuiltinType::Kind::ObjCSel:
|
||||
#define IMAGE_TYPE(it, id, si, a, s) case clang::BuiltinType::Kind::id:
|
||||
#include <clang/Basic/OpenCLImageTypes.def>
|
||||
#undef IMAGE_TYPE
|
||||
case clang::BuiltinType::Kind::OCLSampler:
|
||||
case clang::BuiltinType::Kind::OCLEvent:
|
||||
case clang::BuiltinType::Kind::OCLClkEvent:
|
||||
case clang::BuiltinType::Kind::OCLQueue:
|
||||
case clang::BuiltinType::Kind::OCLReserveID:
|
||||
case clang::BuiltinType::Kind::IncompleteMatrixIdx:
|
||||
case clang::BuiltinType::Kind::OMPArraySection:
|
||||
case clang::BuiltinType::Kind::OMPArrayShaping:
|
||||
case clang::BuiltinType::Kind::OMPIterator:
|
||||
#define EXT_OPAQUE_TYPE(et, id, e) case clang::BuiltinType::Kind::id:
|
||||
#include <clang/Basic/OpenCLExtensionTypes.def>
|
||||
#define SVE_TYPE(n, id, si) case clang::BuiltinType::Kind::id:
|
||||
#include <clang/Basic/AArch64SVEACLETypes.def>
|
||||
#define PPC_VECTOR_TYPE(n, id, s) case clang::BuiltinType::Kind::id:
|
||||
#include <clang/Basic/PPCTypes.def>
|
||||
#undef EXT_OPAQUE_TYPE
|
||||
#undef SVE_TYPE
|
||||
#undef PPC_VECTOR_TYPE
|
||||
return '!';
|
||||
default:
|
||||
return ':';
|
||||
}
|
||||
} else if (qual->isEnumeralType()) {
|
||||
const clang::EnumDecl *ed = qual->getAs<clang::EnumType>()->getDecl();
|
||||
if (!ed) {
|
||||
return 'i';
|
||||
} else {
|
||||
return type2char(ed->getIntegerType().getCanonicalType(), qorig);
|
||||
}
|
||||
} else if (qual->isFunctionPointerType()) {
|
||||
return '@';
|
||||
} else if (qual->isAnyPointerType() || qual->isReferenceType()) {
|
||||
const clang::QualType &pointed = getPointedType(qual);
|
||||
if (isTypeTrivial(pointed, qorig)) {
|
||||
return 'p';
|
||||
} else if (const clang::RecordType *rct = pointed->getAs<clang::RecordType>()) {
|
||||
clang::RecordDecl *rc = rct->getDecl();
|
||||
if (!rc) {
|
||||
return '!';
|
||||
} else if (!rc->isCompleteDefinition()) {
|
||||
return 'p';
|
||||
} else {
|
||||
std::string str;
|
||||
if (qorig) {
|
||||
const clang::QualType qpted = getPointedType(*qorig);
|
||||
str = record2name(*rc, &qpted);
|
||||
} else {
|
||||
str = record2name(*rc, nullptr);
|
||||
}
|
||||
char ret = ptr2char(str);
|
||||
if (ret) return ret;
|
||||
else {
|
||||
return '!';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return '!';
|
||||
}
|
||||
} else if (const clang::RecordType *rct = qual->getAs<clang::RecordType>()) {
|
||||
clang::RecordDecl *rc = rct->getDecl();
|
||||
if (!rc) {
|
||||
return '?';
|
||||
} else if (rc->getNameAsString() == "__builtin_va_list") {
|
||||
// va_list
|
||||
return 'A';
|
||||
} else {
|
||||
return '?';
|
||||
}
|
||||
} else {
|
||||
return '?';
|
||||
}
|
||||
}
|
||||
bool isTypeTrivial(const clang::QualType &q, const clang::QualType *qorig) {
|
||||
const char c = type2char(q, qorig);
|
||||
#define GO(chr) || (c == chr)
|
||||
return (c == 'v')
|
||||
GO('i') GO('u')
|
||||
GO('I') GO('U')
|
||||
GO('l') GO('L')
|
||||
GO('f') GO('d')
|
||||
GO('D') GO('K')
|
||||
GO('0') GO('1')
|
||||
GO('C') GO('c')
|
||||
GO('W') GO('w')
|
||||
GO('H')
|
||||
GO('p');
|
||||
#undef GO
|
||||
}
|
||||
bool isTypeValid(const clang::QualType &q, const clang::QualType *qorig) {
|
||||
const char c = type2char(q, qorig);
|
||||
if (c == 'A') return false;
|
||||
if (c == 'V') return false;
|
||||
return ((c >= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'));
|
||||
}
|
||||
|
||||
const std::string type2string(const clang::QualType &qual, const clang::QualType *qorig) {
|
||||
if (qual->isBuiltinType()) {
|
||||
return std::string("(builtin) ") + static_cast<const clang::BuiltinType&>(*qual).getName(clang::PrintingPolicy{{}}).data();
|
||||
} else if (qual->isFunctionPointerType()) {
|
||||
return "Callback (function pointer)";
|
||||
} else if (qual->isAnyPointerType() || qual->isReferenceType()) {
|
||||
std::string prefix = qual->isAnyPointerType() ? "Pointer to " : "Reference to ";
|
||||
const clang::QualType &pointed = getPointedType(qual);
|
||||
if (isTypeTrivial(pointed, qorig)) {
|
||||
return prefix + "trivial object " + type2string(pointed, qorig) + " (" + type2char(pointed, qorig) + ")";
|
||||
} else if (const clang::RecordType *rct = pointed->getAs<clang::RecordType>()) {
|
||||
clang::RecordDecl *rc = rct->getDecl();
|
||||
if (!rc) {
|
||||
return prefix + "unknown record";
|
||||
} else if (!rc->isCompleteDefinition()) {
|
||||
return prefix + "incomplete record " + rc->getNameAsString();
|
||||
} else {
|
||||
std::string str;
|
||||
if (qorig) {
|
||||
const clang::QualType qpted = getPointedType(*qorig);
|
||||
str = record2name(*rc, &qpted);
|
||||
} else {
|
||||
str = record2name(*rc, nullptr);
|
||||
}
|
||||
const char *ret = ptr2str(str);
|
||||
if (ret[0] != '\0') {
|
||||
return prefix + ret;
|
||||
} else {
|
||||
if (mangler && mangler->shouldMangleDeclName(rc)) {
|
||||
std::string mangled;
|
||||
{
|
||||
llvm::raw_string_ostream strstr{mangled};
|
||||
mangler->mangleName(rc, strstr);
|
||||
}
|
||||
return prefix + "unknown record " + str + " (=== " + mangled + ")";
|
||||
} else {
|
||||
return prefix + "unknown record " + str;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return prefix + "non-trivial or typedef'ed object " + type2string(pointed, qorig) + " (" + type2char(pointed, qorig) + ")";
|
||||
//return "Pointer (maybe to callback)";
|
||||
}
|
||||
} else if (qual->isEnumeralType()) {
|
||||
const clang::EnumDecl *ed = qual->getAs<clang::EnumType>()->getDecl();
|
||||
if (!ed) {
|
||||
return "Enumeration with unknown underlying integer type (assuming int)";
|
||||
} else {
|
||||
return "Enumeration with underlying type " + type2string(ed->getIntegerType().getCanonicalType(), nullptr);
|
||||
}
|
||||
} else if (const clang::RecordType *rct = qual->getAs<clang::RecordType>()) {
|
||||
clang::RecordDecl *rc = rct->getDecl();
|
||||
if (!rc) {
|
||||
return "Unknown record";
|
||||
} else if (rc->getNameAsString() == "__builtin_va_list") {
|
||||
return "va_list";
|
||||
} else {
|
||||
return "Unknown record " + std::string(rc->getName().data());
|
||||
}
|
||||
} else {
|
||||
return std::string("??? ") + qual->getTypeClassName();
|
||||
}
|
||||
}
|
||||
|
||||
class Visitor : public clang::RecursiveASTVisitor<Visitor> {
|
||||
public:
|
||||
clang::ASTContext &context;
|
||||
|
||||
bool shouldVisitTemplateInstantiations() const /* override */ { return true; }
|
||||
|
||||
Visitor(clang::CompilerInstance &ci) : context(ci.getASTContext()) {
|
||||
if (!mangler) {
|
||||
mangler = clang::ItaniumMangleContext::create(context, ci.getDiagnostics());
|
||||
}
|
||||
}
|
||||
|
||||
~Visitor() {
|
||||
if (mangler) {
|
||||
delete mangler;
|
||||
mangler = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool VisitDecl(clang::Decl *decl) /* override */ {
|
||||
std::cerr << std::flush;
|
||||
if (!decl) return true;
|
||||
|
||||
if ((decl->getKind() >= clang::Decl::Kind::firstFunction) && (decl->getKind() <= clang::Decl::Kind::lastFunction)) {
|
||||
clang::DeclaratorDecl *ddecl = static_cast<clang::DeclaratorDecl*>(decl);
|
||||
std::cout << "Function detected!\n";
|
||||
|
||||
std::string funName{ddecl->getName()};
|
||||
|
||||
auto niceprint = [](const std::string &infotype, const auto &dat){ std::cout << " " << infotype << ": " << dat << "\n"; };
|
||||
niceprint("Function name", funName);
|
||||
if (mangler && mangler->shouldMangleDeclName(ddecl)) {
|
||||
std::string mangled;
|
||||
{
|
||||
llvm::raw_string_ostream strstr{mangled};
|
||||
mangler->mangleName(ddecl, strstr);
|
||||
}
|
||||
niceprint("Function mangled name", mangled);
|
||||
funName = std::move(mangled);
|
||||
}
|
||||
|
||||
bool valid;
|
||||
std::string funTypeStr{""};
|
||||
if (ddecl->getFunctionType()->isFunctionNoProtoType()) {
|
||||
const clang::FunctionNoProtoType *funType = static_cast<const clang::FunctionNoProtoType*>(ddecl->getFunctionType());
|
||||
const auto &retType = funType->getReturnType();
|
||||
|
||||
niceprint("Function return type", type2string(retType, &retType));
|
||||
niceprint("Canonical function return type",
|
||||
type2string(retType.getCanonicalType(), &retType) +
|
||||
" (" + type2char(retType.getCanonicalType(), &retType) + ")");
|
||||
niceprint("Is sugared", funType->isSugared());
|
||||
if (funType->isSugared()) {
|
||||
clang::QualType qft{funType, 0};
|
||||
niceprint("Desugared", type2string(funType->desugar(), &qft));
|
||||
}
|
||||
|
||||
funTypeStr = type2char(retType.getCanonicalType(), &retType) + std::string("Fv");
|
||||
valid = isTypeValid(retType.getCanonicalType(), &retType);
|
||||
} else {
|
||||
const clang::FunctionProtoType *funType = static_cast<const clang::FunctionProtoType*>(ddecl->getFunctionType());
|
||||
const auto &retType = funType->getReturnType();
|
||||
|
||||
niceprint("Function return type", type2string(retType, &retType));
|
||||
niceprint("Canonical function return type",
|
||||
type2string(retType.getCanonicalType(), &retType)
|
||||
+ " (" + type2char(retType.getCanonicalType(), &retType) + ")");
|
||||
niceprint("Parameter count", funType->getNumParams());
|
||||
for (const clang::QualType &type : funType->getParamTypes()) {
|
||||
niceprint(" " + type2string(type, &type),
|
||||
type2string(type.getCanonicalType(), &type) + " (" + type2char(type.getCanonicalType(), &type) + ")");
|
||||
}
|
||||
niceprint("Variadic function", funType->isVariadic() ? "yes" : "no");
|
||||
|
||||
funTypeStr =
|
||||
type2char(retType.getCanonicalType(), &retType) +
|
||||
((funType->getNumParams() == 0)
|
||||
? std::string("Fv") : std::accumulate(funType->getParamTypes().begin(), funType->getParamTypes().end(), std::string("F"),
|
||||
[](const std::string &acc, const clang::QualType &qual){ return acc + type2char(qual.getCanonicalType(), &qual); }));
|
||||
if (funType->isVariadic()) funTypeStr += "V";
|
||||
valid = !funType->isVariadic() &&
|
||||
std::accumulate(funType->getParamTypes().begin(), funType->getParamTypes().end(), isTypeValid(retType.getCanonicalType(), &retType),
|
||||
[](bool acc, const clang::QualType &qual){ return acc && isTypeValid(qual.getCanonicalType(), &qual); });
|
||||
}
|
||||
|
||||
niceprint("Conclusion", "");
|
||||
niceprint("Function final name", funName);
|
||||
niceprint("Function type", funTypeStr);
|
||||
niceprint("Valid function type", valid ? "yes" : "no");
|
||||
std::cout << "\n";
|
||||
|
||||
funMap[funName] = std::make_pair(funTypeStr, valid);
|
||||
funList.push_back(funName);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class Consumer : public clang::ASTConsumer {
|
||||
public:
|
||||
Visitor visitor;
|
||||
|
||||
Consumer(clang::CompilerInstance &ci) : visitor(ci) {
|
||||
}
|
||||
|
||||
void HandleTranslationUnit(clang::ASTContext &context) override {
|
||||
visitor.TraverseDecl(context.getTranslationUnitDecl());
|
||||
}
|
||||
};
|
||||
|
||||
class Action : public clang::ASTFrontendAction {
|
||||
public:
|
||||
virtual std::unique_ptr<clang::ASTConsumer> CreateASTConsumer(clang::CompilerInstance &ci, llvm::StringRef inFile) override {
|
||||
return std::make_unique<Consumer>(ci);
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, const char **argv) {
|
||||
if (argc < 2) {
|
||||
std::cerr << "Usage: " << argv[0] << " (filenames) -- [-I...]" << std::endl;
|
||||
return 2;
|
||||
}
|
||||
|
||||
/*int fakeargc = argc + 1;
|
||||
const char **fakeargv = new const char*[fakeargc];
|
||||
memcpy(fakeargv, argv, argc * sizeof(char*));
|
||||
fakeargv[fakeargc - 1] = "--";*/
|
||||
llvm::cl::OptionCategory opcat{""};
|
||||
clang::tooling::CommonOptionsParser op{argc, argv, opcat};
|
||||
std::vector<std::string> paths; for (int i = 1; i < argc; ++i) paths.push_back(argv[i]);
|
||||
|
||||
clang::tooling::ClangTool tool{op.getCompilations(), paths};
|
||||
|
||||
tool.run(clang::tooling::newFrontendActionFactory<Action>().get());
|
||||
|
||||
std::cout << "Done, outputing output.h" << std::endl;
|
||||
std::sort(funList.begin(), funList.end());
|
||||
std::fstream file{"output.h", std::ios_base::out};
|
||||
for (const std::string &funName : funList) {
|
||||
if (!funMap[funName].second) {
|
||||
file << "//";
|
||||
}
|
||||
file << "GO(" << funName << ", " << funMap[funName].first << ")\n";
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,267 @@
|
||||
#include <string>
|
||||
|
||||
#define ALL START() \
|
||||
/* libc */ \
|
||||
STRUCT("_IO_FILE", "a FILE") \
|
||||
STRUCT("_G_fpos_t", "a file position") \
|
||||
STRUCT("sockaddr", "a socket address") \
|
||||
STRUCT("itimerspec", "an itimerspec") \
|
||||
STRUCT("timespec", "a timespec") \
|
||||
STRUCT("itimerval", "an itimerval") \
|
||||
STRUCT("timeval", "a timeval") \
|
||||
STRUCT("timex", "a timex") \
|
||||
STRUCT("timezone", "a timezone") \
|
||||
STRUCT("dirent", "a dirent") \
|
||||
STRUCT("dirent64", "a dirent64") \
|
||||
STRUCT("__dirstream", "a dir stream") \
|
||||
STRUCT("tm", "a time structure (tm)") \
|
||||
STRUCT("cmsghdr", "a cmsghdr") \
|
||||
STRUCT("msghdr", "a msghdr") \
|
||||
STRUCT("rpcent", "an rpcent") \
|
||||
STRUCT("random_data", "a random_data structure") \
|
||||
STRUCT("drand48_data", "a drand48_data structure") \
|
||||
STRUCT("termios", "a termios") \
|
||||
STRUCT("iovec", "an iovec") \
|
||||
STRUCT("file_handle", "a file handle") \
|
||||
STRUCT("lconv", "an lconv") \
|
||||
STRUCT("__locale_struct", "a locale structure") \
|
||||
STRUCT("aliasent", "an alias") \
|
||||
STRUCT("fstab", "an fstab") \
|
||||
STRUCT("group", "a group") \
|
||||
STRUCT("hostent", "a hostent") \
|
||||
STRUCT("protoent", "a protoent") \
|
||||
STRUCT("passwd", "a password") \
|
||||
STRUCT("spwd", "an spwd") \
|
||||
STRUCT("ttyent", "a ttyent") \
|
||||
STRUCT("utmp", "an utmp structure") \
|
||||
STRUCT("utmpx", "an utmpx structure") \
|
||||
STRUCT("ifaddrs", "an ifaddrs structure") \
|
||||
STRUCT("statfs", "a statfs structure") \
|
||||
STRUCT("statfs64", "a statfs64 structure") \
|
||||
STRUCT("statvfs", "a statvfs structure") \
|
||||
STRUCT("statvfs64", "a statvfs64 structure") \
|
||||
STRUCT("timeb", "a timeb structure") \
|
||||
STRUCT("_ftsent", "an _ftsent structure") \
|
||||
STRUCT("sysinfo", "a sysinfo structure") \
|
||||
STRUCT("rlimit", "an rlimit structure") \
|
||||
STRUCT("rlimit64", "an rlimit64 structure") \
|
||||
STRUCT("rusage", "an rusage structure") \
|
||||
STRUCT("entry", "an entry structure") \
|
||||
STRUCT("pollfd", "a pollfd structure") \
|
||||
STRUCT("re_pattern_buffer", "a re_pattern_buffer structure") \
|
||||
STRUCT("sembuf", "a sembuf structure") \
|
||||
STRUCT("tms", "a tms structure") \
|
||||
STRUCT("utsname", "an utsname structure") \
|
||||
STRUCT("utimbuf", "an utimbuf structure") \
|
||||
STRUCT2("__va_list_tag", "__va_list_tag (aka, a va_list)", 'A') \
|
||||
/* ncurses */ \
|
||||
STRUCT("_win_st", "a _win_st structure") \
|
||||
STRUCT("MEVENT", "an MEVENT structure") \
|
||||
TYPEDEF("cchar_t", "a cchar_t") \
|
||||
/* zlib */ \
|
||||
STRUCT("gz_header_s", "a gz_header_s structure") \
|
||||
STRUCT("gzFile_s", "a gzFile_s structure") \
|
||||
STRUCT("z_stream_s", "a z_stream_s structure") \
|
||||
\
|
||||
END()
|
||||
|
||||
#define START()
|
||||
#define STRUCT(s, ret) if (str == s) { return 'p'; } else
|
||||
#define STRUCT2(s, ret, c) if (str == s) { return c; } else
|
||||
#define TYPEDEF(s, ret) if (str == s) { return 'p'; } else
|
||||
#define END() { return 0; }
|
||||
char ptr2char(const std::string &str) {
|
||||
/*if ((str == "_IO_FILE")
|
||||
|| (str == "_G_fpos_t")
|
||||
|| (str == "sockaddr")
|
||||
|| (str == "itimerspec")
|
||||
|| (str == "timespec")
|
||||
|| (str == "itimerval")
|
||||
|| (str == "timeval")
|
||||
|| (str == "timex")
|
||||
|| (str == "timezone")
|
||||
|| (str == "dirent")
|
||||
|| (str == "dirent64")
|
||||
|| (str == "__dirstream")
|
||||
|| (str == "tm")
|
||||
|| (str == "cmsghdr")
|
||||
|| (str == "msghdr")
|
||||
|| (str == "rpcent")
|
||||
|| (str == "random_data")
|
||||
|| (str == "drand48_data")
|
||||
|| (str == "termios")
|
||||
|| (str == "iovec")
|
||||
|| (str == "file_handle")
|
||||
|| (str == "lconv")
|
||||
|| (str == "__locale_struct")
|
||||
|| (str == "aliasent")
|
||||
|| (str == "fstab")
|
||||
|| (str == "group")
|
||||
|| (str == "hostent")
|
||||
|| (str == "protoent")
|
||||
|| (str == "passwd")
|
||||
|| (str == "spwd")
|
||||
|| (str == "ttyent")
|
||||
|| (str == "utmp")
|
||||
|| (str == "utmpx")
|
||||
|| (str == "ifaddrs")
|
||||
|| (str == "statfs")
|
||||
|| (str == "statfs64")
|
||||
|| (str == "statvfs")
|
||||
|| (str == "timeb")
|
||||
|| (str == "_ftsent")
|
||||
|| (str == "sysinfo")
|
||||
|| (str == "rlimit")
|
||||
|| (str == "rlimit64")
|
||||
|| (str == "rusage")
|
||||
|| (str == "entry")
|
||||
|| (str == "pollfd")
|
||||
|| (str == "re_pattern_buffer")
|
||||
|| (str == "sembuf")
|
||||
|| (str == "tms")
|
||||
|| (str == "utsname")
|
||||
|| (str == "utimbuf")
|
||||
// ncurses
|
||||
|| (str == "_win_st")
|
||||
|
||||
|| (str == "cchar_t")
|
||||
) {
|
||||
// FILE*, fpos_t*, ...
|
||||
return 'p';
|
||||
} else if (str == "__va_list_tag") {
|
||||
return 'A';
|
||||
} else {
|
||||
return 0;
|
||||
}*/
|
||||
ALL
|
||||
}
|
||||
#undef END
|
||||
#undef TYPEDEF
|
||||
#undef STRUCT2
|
||||
#undef STRUCT
|
||||
#undef START
|
||||
|
||||
#define START()
|
||||
#define STRUCT(s, ret) if (str == s) { return ret; } else
|
||||
#define STRUCT2(s, ret, c) if (str == s) { return ret; } else
|
||||
#define TYPEDEF(s, ret) if (str == s) { return ret; } else
|
||||
#define END() return "";
|
||||
const char *ptr2str(const std::string &str) {
|
||||
/*if (str == "_IO_FILE") {
|
||||
return "a FILE";
|
||||
} else if (str == "_G_fpos_t") {
|
||||
return "a file position";
|
||||
} else if (str == "sockaddr") {
|
||||
return "a socket address";
|
||||
} else if (str == "itimerspec") {
|
||||
return "an itimerspec";
|
||||
} else if (str == "timespec") {
|
||||
return "a timespec";
|
||||
} else if (str == "itimerval") {
|
||||
return "an itimerval";
|
||||
} else if (str == "timeval") {
|
||||
return "a timeval";
|
||||
} else if (str == "timex") {
|
||||
return "a timex";
|
||||
} else if (str == "timezone") {
|
||||
return "a timezone";
|
||||
} else if (str == "dirent") {
|
||||
return "a dirent";
|
||||
} else if (str == "dirent64") {
|
||||
return "a dirent64";
|
||||
} else if (str == "__dirstream") {
|
||||
return "a dir stream";
|
||||
} else if (str == "tm") {
|
||||
return "a time structure (tm)";
|
||||
} else if (str == "cmsghdr") {
|
||||
return "a cmsghdr";
|
||||
} else if (str == "msghdr") {
|
||||
return "a msghdr";
|
||||
} else if (str == "rpcent") {
|
||||
return "an rpcent";
|
||||
} else if (str == "random_data") {
|
||||
return "a random_data structure";
|
||||
} else if (str == "drand48_data") {
|
||||
return "a drand48_data structure";
|
||||
} else if (str == "termios") {
|
||||
return "a termios";
|
||||
} else if (str == "iovec") {
|
||||
return "an iovec";
|
||||
} else if (str == "file_handle") {
|
||||
return "a file handle";
|
||||
} else if (str == "lconv") {
|
||||
return "an lconv";
|
||||
} else if (str == "__locale_struct") {
|
||||
return "a locale structure";
|
||||
} else if (str == "aliasent") {
|
||||
return "an alias";
|
||||
} else if (str == "fstab") {
|
||||
return "an fstab";
|
||||
} else if (str == "group") {
|
||||
return "a group";
|
||||
} else if (str == "hostent") {
|
||||
return "a hostent";
|
||||
} else if (str == "protoent") {
|
||||
return "a protoent";
|
||||
} else if (str == "passwd") {
|
||||
return "a password";
|
||||
} else if (str == "spwd") {
|
||||
return "an spwd";
|
||||
} else if (str == "ttyent") {
|
||||
return "a ttyent";
|
||||
} else if (str == "utmp") {
|
||||
return "an utmp structure";
|
||||
} else if (str == "utmpx") {
|
||||
return "an utmpx structure";
|
||||
} else if (str == "ifaddrs") {
|
||||
return "an ifaddrs structure";
|
||||
} else if (str == "statfs") {
|
||||
return "a statfs structure";
|
||||
} else if (str == "statfs64") {
|
||||
return "a statfs64 structure";
|
||||
} else if (str == "statvfs") {
|
||||
return "a statvfs structure";
|
||||
} else if (str == "statvfs64") {
|
||||
return "a statvfs64 structure";
|
||||
} else if (str == "timeb") {
|
||||
return "a timeb structure";
|
||||
} else if (str == "_ftsent") {
|
||||
return "an _ftsent structure";
|
||||
} else if (str == "sysinfo") {
|
||||
return "a sysinfo structure";
|
||||
} else if (str == "rlimit") {
|
||||
return "an rlimit structure";
|
||||
} else if (str == "rlimit64") {
|
||||
return "an rlimit64 structure";
|
||||
} else if (str == "rusage") {
|
||||
return "an rusage structure";
|
||||
} else if (str == "entry") {
|
||||
return "an entry structure";
|
||||
} else if (str == "pollfd") {
|
||||
return "a pollfd structure";
|
||||
} else if (str == "re_pattern_buffer") {
|
||||
return "a re_pattern_buffer structure";
|
||||
} else if (str == "sembuf") {
|
||||
return "a sembuf structure";
|
||||
} else if (str == "tms") {
|
||||
return "a tms structure";
|
||||
} else if (str == "utsname") {
|
||||
return "an utsname structure";
|
||||
} else if (str == "utimbuf") {
|
||||
return "an utimbuf structure";
|
||||
} else if (str == "__va_list_tag") {
|
||||
return "__va_list_tag (aka, a va_list)";
|
||||
// ncurses
|
||||
} else if (str == "_win_st") {
|
||||
return "a _win_st structure";
|
||||
|
||||
} else if (str == "cchar_t") {
|
||||
return "a cchar_t";
|
||||
} else return "";*/
|
||||
ALL
|
||||
}
|
||||
#undef END
|
||||
#undef TYPEDEF
|
||||
#undef STRUCT2
|
||||
#undef STRUCT
|
||||
#undef START
|
||||
Reference in new issue
Block a user