diff options
| author | rajdakin <rajdakin@gmail.com> | 2021-08-01 17:12:36 +0200 |
|---|---|---|
| committer | rajdakin <rajdakin@gmail.com> | 2021-08-01 17:12:36 +0200 |
| commit | f014d4580a8eea1ae3082544d973274681e2059c (patch) | |
| tree | b9d31a6231eed6682489fbddc1ecb76b799e6c30 | |
| parent | 1f02ab17e37ac2ed766a9434449af5f58d627613 (diff) | |
| download | box64-f014d4580a8eea1ae3082544d973274681e2059c.tar.gz box64-f014d4580a8eea1ae3082544d973274681e2059c.zip | |
Added a useful script
| -rw-r--r-- | .gitignore | 5 | ||||
| -rw-r--r-- | LLVMprivateGenerator/Makefile | 12 | ||||
| -rw-r--r-- | LLVMprivateGenerator/main.cpp | 458 | ||||
| -rw-r--r-- | LLVMprivateGenerator/registered_structs.cpp | 267 |
4 files changed, 742 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore index 3d60185f..2df9f7d3 100644 --- a/.gitignore +++ b/.gitignore @@ -59,3 +59,8 @@ build*/ src/git_head.h backup/ +# LLVMprivateGenerator +/LLVMprivateGenerator/* +!/LLVMprivateGenerator/Makefile +!/LLVMprivateGenerator/main.cpp +!/LLVMprivateGenerator/registered_structs.cpp diff --git a/LLVMprivateGenerator/Makefile b/LLVMprivateGenerator/Makefile new file mode 100644 index 00000000..61864262 --- /dev/null +++ b/LLVMprivateGenerator/Makefile @@ -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 diff --git a/LLVMprivateGenerator/main.cpp b/LLVMprivateGenerator/main.cpp new file mode 100644 index 00000000..fe070cb0 --- /dev/null +++ b/LLVMprivateGenerator/main.cpp @@ -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; +} diff --git a/LLVMprivateGenerator/registered_structs.cpp b/LLVMprivateGenerator/registered_structs.cpp new file mode 100644 index 00000000..0473deb5 --- /dev/null +++ b/LLVMprivateGenerator/registered_structs.cpp @@ -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 |