32 #ifndef _QORE_MODULEINFO_H
34 #define _QORE_MODULEINFO_H
36 #ifdef NEED_DLFCN_WRAPPER
40 #ifdef NEED_DLFCN_WRAPPER
51 #define MOD_HEADER_PO (PO_LOCKDOWN & ~PO_NO_MODULES)
54 #define USER_MOD_PO (PO_NO_TOP_LEVEL_STATEMENTS | PO_REQUIRE_PROTOTYPES | PO_REQUIRE_OUR | PO_IN_MODULE)
58 #define QMLO_INJECT (1 << 0)
59 #define QMLO_REINJECT (1 << 1)
60 #define QMLO_PRIVATE (1 << 2)
61 #define QMLO_RELOAD (1 << 3)
76 DLLLOCAL
char set(
const char* v);
83 DLLLOCAL
const char* operator*()
const {
88 class QoreAbstractModule {
91 DLLLOCAL QoreAbstractModule(
const QoreAbstractModule&);
92 DLLLOCAL QoreAbstractModule& operator=(
const QoreAbstractModule&);
104 QoreAbstractModule* prev =
nullptr,
111 DLLLOCAL
QoreHashNode* getHashIntern(
bool with_filename =
true)
const;
115 DLLLOCAL
void set(
const char* d,
const char* v,
const char* a,
const char* u,
const QoreString& l) {
129 DLLLOCAL QoreAbstractModule(
const char* cwd,
const char* fn,
const char* n,
const char* d,
const char* v,
130 const char* a,
const char* u,
const QoreString& l) : filename(fn), name(n), desc(d), author(a), url(u),
131 license(l), priv(false), injected(false), reinjected(false), version_list(v) {
136 DLLLOCAL QoreAbstractModule(
const char* cwd,
const char* fn,
const char* n,
unsigned load_opt) :
137 filename(fn), name(n), priv(load_opt & QMLO_PRIVATE), injected(load_opt & QMLO_INJECT),
138 reinjected(load_opt & QMLO_REINJECT) {
142 DLLLOCAL
virtual ~QoreAbstractModule() {
145 assert(next->prev ==
this);
149 assert(prev->next ==
this);
154 DLLLOCAL
const char* getName()
const {
158 DLLLOCAL
const char* getFileName()
const {
162 DLLLOCAL
const QoreString& getFileNameStr()
const {
166 DLLLOCAL
const char* getDesc()
const {
170 DLLLOCAL
const char* getVersion()
const {
171 return* version_list;
174 DLLLOCAL
const char* getURL()
const {
178 DLLLOCAL
const char* getOrigName()
const {
182 DLLLOCAL
void resetName() {
183 assert(!orig_name.
empty());
188 DLLLOCAL
bool isInjected()
const {
192 DLLLOCAL
bool isReInjected()
const {
196 DLLLOCAL
void addModuleReExport(
const char* m) {
203 addToProgramImpl(pgm, xsink);
205 reexport(xsink, pgm);
208 DLLLOCAL
bool equalTo(
const QoreAbstractModule* m)
const {
209 assert(name == m->name);
210 return filename == m->filename;
213 DLLLOCAL
bool isPath(
const char* p)
const {
214 return filename == p;
218 assert(orig_name.
empty());
222 DLLLOCAL
void setOrigName(
const char* n) {
223 assert(orig_name.
empty());
227 DLLLOCAL
bool isPrivate()
const {
231 DLLLOCAL
void setPrivate(
bool p =
true) {
236 DLLLOCAL
void setLink(QoreAbstractModule* n) {
244 DLLLOCAL QoreAbstractModule* getNext()
const {
248 DLLLOCAL
virtual bool isBuiltin()
const = 0;
249 DLLLOCAL
virtual bool isUser()
const = 0;
250 DLLLOCAL
virtual QoreHashNode* getHash(
bool with_filename =
true)
const = 0;
251 DLLLOCAL
virtual void issueModuleCmd(
const QoreProgramLocation* loc,
const QoreString& cmd,
ExceptionSink* xsink) = 0;
255 typedef std::deque<std::string> strdeque_t;
263 typedef std::set<std::string> strset_t;
269 DLLLOCAL
void addDirList(
const char* str);
271 DLLLOCAL
bool push_back(
const std::string &str) {
272 if (dset.find(str) != dset.end()) {
275 dlist.push_back(str);
280 DLLLOCAL
bool empty()
const {
281 return dlist.empty();
284 DLLLOCAL strdeque_t::const_iterator begin()
const {
285 return dlist.begin();
288 DLLLOCAL strdeque_t::const_iterator end()
const {
292 DLLLOCAL
void appendPath(
QoreString& str)
const {
297 for (strdeque_t::const_iterator i = dlist.begin(), e = dlist.end(); i != e; ++i) {
305 class QoreModuleContextHelper :
public QoreModuleContext {
308 DLLLOCAL ~QoreModuleContextHelper();
311 class QoreModuleDefContextHelper :
public QoreModuleDefContext {
313 QoreModuleDefContext* old;
316 DLLLOCAL QoreModuleDefContextHelper() : old(set_module_def_context(this)) {
319 DLLLOCAL ~QoreModuleDefContextHelper() {
320 set_module_def_context(old);
324 class QoreUserModuleDefContextHelper;
325 class QoreUserModule;
327 typedef std::set<std::string> strset_t;
328 typedef std::map<std::string, strset_t> md_map_t;
332 DLLLOCAL ModMap(
const ModMap &);
333 DLLLOCAL ModMap& operator=(
const ModMap&);
345 DLLLOCAL
bool addDep(
const char* l,
const char* r) {
346 md_map_t::iterator i = map.lower_bound(l);
347 if (i == map.end() || i->first != l)
348 i = map.insert(i, md_map_t::value_type(l, strset_t()));
349 else if (i->second.find(r) != i->second.end())
355 DLLLOCAL md_map_t::iterator begin() {
359 DLLLOCAL md_map_t::iterator end() {
363 DLLLOCAL md_map_t::iterator find(
const char* n) {
367 DLLLOCAL md_map_t::iterator find(
const std::string& n) {
371 DLLLOCAL
void erase(md_map_t::iterator i) {
375 DLLLOCAL
void clear() {
379 DLLLOCAL
bool empty()
const {
384 DLLLOCAL
void show(
const char* name) {
385 printf(
"ModMap '%s':\n", name);
386 for (md_map_t::iterator i = map.begin(), e = map.end(); i != e; ++i) {
388 for (strset_t::iterator si = i->second.begin(), se = i->second.end(); si != se; ++si)
389 str.sprintf(
"'%s',", (*si).c_str());
392 printd(0,
" + %s '%s' -> %s\n", name, i->first.c_str(), str.getBuffer());
401 DLLLOCAL DLHelper(
void* p) : ptr(p) {
404 DLLLOCAL ~DLHelper() {
409 DLLLOCAL
void* release() {
416 class QoreModuleManager {
417 friend class QoreAbstractModule;
418 friend class ModuleLoadMapHelper;
421 DLLLOCAL QoreModuleManager() {
424 DLLLOCAL ~QoreModuleManager() {
427 DLLLOCAL
void init(
bool se);
428 DLLLOCAL
void delUser();
429 DLLLOCAL
void cleanup();
431 DLLLOCAL
void issueParseCmd(
const QoreProgramLocation* loc,
const char* mname,
const QoreString& cmd);
435 DLLLOCAL
void addModule(QoreAbstractModule* m) {
436 assert(map.find(m->getName()) == map.end());
437 map.insert(module_map_t::value_type(m->getName(), m));
440 DLLLOCAL QoreAbstractModule* findModule(
const char* name) {
442 return findModuleUnlocked(name);
446 bool reexport =
false);
448 QoreProgram* mpgm =
nullptr,
unsigned load_opt = QMLO_NONE,
int warning_mask = QP_WARN_MODULES,
454 DLLLOCAL
void addModuleDir(
const char* dir) {
456 moduleDirList.push_back(dir);
459 DLLLOCAL
void addModuleDirList(
const char* strlist) {
461 moduleDirList.addDirList(strlist);
464 DLLLOCAL
void addStandardModulePaths();
466 DLLLOCAL
void registerUserModuleFromSource(
const char* name,
const char* src,
QoreProgram *pgm,
ExceptionSink& xsink);
468 DLLLOCAL
void trySetUserModuleDependency(
const QoreAbstractModule* mi) {
472 const char* old_name = get_user_module_context_name();
474 setUserModuleDependency(mi->getName(), old_name);
475 trySetUserModule(mi->getName());
478 DLLLOCAL
void trySetUserModule(
const char* name) {
479 md_map_t::iterator i = md_map.find(name);
480 if (i == md_map.end()) {
497 DLLLOCAL
void setUserModuleDependency(
const char* name,
const char* dep) {
499 if (md_map.addDep(name, dep))
501 rmd_map.addDep(dep, name);
503 strset_t::iterator ui = umset.find(name);
504 if (ui != umset.end()) {
510 DLLLOCAL
void removeUserModuleDependency(
const char* name,
const char* orig_name = 0) {
512 md_map_t::iterator i = rmd_map.find(name);
513 if (i == rmd_map.end() && orig_name)
514 i = rmd_map.find(orig_name);
515 if (i != rmd_map.end()) {
517 for (strset_t::iterator si = i->second.begin(), se = i->second.end(); si != se; ++si) {
518 md_map_t::iterator di = md_map.find(*si);
519 assert(di != md_map.end());
521 strset_t::iterator dsi = di->second.find(i->first);
522 assert(dsi != di->second.end());
523 di->second.erase(dsi);
524 if (di->second.empty()) {
527 assert(umset.find(*si) == umset.end());
535 i = md_map.find(name);
536 if (i != md_map.end())
539 i = md_map.find(orig_name);
540 if (i != md_map.end())
547 DLLLOCAL QoreModuleManager(
const QoreModuleManager&);
549 DLLLOCAL QoreModuleManager& operator=(
const QoreModuleManager&);
551 DLLLOCAL QoreAbstractModule* loadSeparatedModule(
557 bool reexport =
false,
560 unsigned load_opt = QMLO_NONE,
561 int warning_mask = QP_WARN_MODULES);
563 typedef std::map<std::string, int> module_load_map_t;
566 module_load_map_t module_load_map;
568 int module_load_waiting = 0;
580 typedef std::map<const char*, const char*, ltstr> bl_map_t;
581 bl_map_t mod_blacklist;
584 typedef std::map<const char*, QoreAbstractModule*, ltstr> module_map_t;
593 DLLLOCAL QoreAbstractModule* findModuleUnlocked(
const char* name) {
594 module_map_t::iterator i = map.find(name);
595 return i == map.end() ? 0 : i->second;
601 loadModuleIntern(xsink, xsink, name, pgm);
605 bool reexport =
false, mod_op_e op = MOD_OP_NONE,
version_list_t* version =
nullptr,
606 const char* src =
nullptr,
QoreProgram* mpgm =
nullptr,
unsigned load_opt = QMLO_NONE,
609 DLLLOCAL QoreAbstractModule* loadBinaryModuleFromPath(
ExceptionSink& xsink,
const char* path,
610 const char* feature =
nullptr,
QoreProgram* pgm =
nullptr,
bool reexport =
false,
613 DLLLOCAL QoreAbstractModule* loadBinaryModuleFromDesc(
ExceptionSink& xsink, DLHelper* dlh,
615 bool reexport =
false);
618 const char* feature =
nullptr,
QoreProgram* tpgm =
nullptr,
bool reexport =
false,
QoreProgram* pgm =
nullptr,
619 QoreProgram* path_pgm =
nullptr,
unsigned load_opt = QMLO_NONE,
int warning_mask = QP_WARN_MODULES);
623 int warning_mask = QP_WARN_MODULES);
625 DLLLOCAL QoreAbstractModule* setupUserModule(
ExceptionSink& xsink, std::unique_ptr<QoreUserModule>& mi,
626 QoreUserModuleDefContextHelper& qmd,
unsigned load_opt = QMLO_NONE,
int warning_mask = QP_WARN_MODULES);
628 DLLLOCAL
void reinjectModule(QoreAbstractModule* mi);
629 DLLLOCAL
void delOrig(QoreAbstractModule* mi);
630 DLLLOCAL
void getUniqueName(
QoreString& nname,
const char* name,
const char* prefix);
633 DLLLOCAL
extern QoreModuleManager QMM;
635 class QoreBuiltinModule :
public QoreAbstractModule {
637 unsigned api_major, api_minor;
648 DLLLOCAL QoreBuiltinModule(
const char* cwd,
const char* fn,
const char* n,
const char* d,
const char* v,
652 : QoreAbstractModule(cwd, fn, n, d, v, a, u, l), api_major(major), api_minor(minor), module_init(init),
653 module_ns_init(ns_init), module_delete(del), module_parse_cmd(pcmd), info(info), dlptr(p) {
656 DLLLOCAL
virtual ~QoreBuiltinModule() {
657 printd(5,
"QoreBuiltinModule::~QoreBuiltinModule() '%s': %s calling module_delete: %p\n", name.getBuffer(), filename.
getBuffer(), module_delete);
663 DLLLOCAL
unsigned getAPIMajor()
const {
667 DLLLOCAL
unsigned getAPIMinor()
const {
671 DLLLOCAL
virtual bool isBuiltin()
const override {
675 DLLLOCAL
virtual bool isUser()
const override {
679 DLLLOCAL
QoreHashNode* getHash(
bool with_filename =
true)
const override;
681 DLLLOCAL
const void* getPtr()
const {
685 DLLLOCAL
virtual void issueModuleCmd(
const QoreProgramLocation* loc,
const QoreString& cmd,
ExceptionSink* xsink)
override;
688 class QoreUserModule :
public QoreAbstractModule {
696 DLLLOCAL QoreUserModule(
const char* cwd,
const char* fn,
const char* n,
QoreProgram* p,
unsigned load_opt,
697 int warning_mask = QP_WARN_MODULES) : QoreAbstractModule(cwd, fn, n, load_opt), pgm(p) {
701 QoreAbstractModule::set(d, v, a, u, l);
709 DLLLOCAL
virtual ~QoreUserModule();
711 DLLLOCAL
virtual bool isBuiltin()
const override {
715 DLLLOCAL
virtual bool isUser()
const override {
719 DLLLOCAL
virtual QoreHashNode* getHash(
bool with_filename =
true)
const override {
720 return getHashIntern(with_filename);
723 DLLLOCAL
virtual void issueModuleCmd(
const QoreProgramLocation* loc,
const QoreString& cmd,
ExceptionSink* xsink)
override {
725 xsink->
raiseException(*loc,
"PARSE-COMMAND-ERROR",
"module '%s' loaded from '%s' is a user module; only builtin modules can support parse commands",
726 name.c_str(), filename.
c_str());
731 class QoreUserModuleDefContextHelper :
public QoreModuleDefContextHelper {
735 DLLLOCAL ~QoreUserModuleDefContextHelper() {
736 const char* name = set_user_module_context_name(old_name);
739 QMM.removeUserModuleDependency(name);
742 DLLLOCAL
void setDuplicate() {
747 DLLLOCAL
void setNameInit(
const char* name);
749 DLLLOCAL
void close();
752 const char* old_name;
754 qore_program_private* pgm;
761 class ModuleLoadMapHelper {
763 DLLLOCAL ModuleLoadMapHelper(
const char* feature);
764 DLLLOCAL ~ModuleLoadMapHelper();
767 QoreModuleManager::module_load_map_t::iterator i;