Qore Programming Language  1.12.0
ModuleInfo.h
1 /* -*- mode: c++; indent-tabs-mode: nil -*- */
2 /*
3  ModuleInfo.h
4 
5  Qore Programming Language
6 
7  Copyright (C) 2003 - 2022 Qore Technologies, s.r.o.
8 
9  Permission is hereby granted, free of charge, to any person obtaining a
10  copy of this software and associated documentation files (the "Software"),
11  to deal in the Software without restriction, including without limitation
12  the rights to use, copy, modify, merge, publish, distribute, sublicense,
13  and/or sell copies of the Software, and to permit persons to whom the
14  Software is furnished to do so, subject to the following conditions:
15 
16  The above copyright notice and this permission notice shall be included in
17  all copies or substantial portions of the Software.
18 
19  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25  DEALINGS IN THE SOFTWARE.
26 
27  Note that the Qore library is released under a choice of three open-source
28  licenses: MIT (as above), LGPL 2+, or GPL 2+; see README-LICENSE for more
29  information.
30 */
31 
32 #ifndef _QORE_MODULEINFO_H
33 
34 #define _QORE_MODULEINFO_H
35 
36 #ifdef NEED_DLFCN_WRAPPER
37 extern "C" {
38 #endif
39 #include <dlfcn.h>
40 #ifdef NEED_DLFCN_WRAPPER
41 }
42 #endif
43 
44 #include <string>
45 #include <map>
46 #include <deque>
47 #include <memory>
48 #include <vector>
49 
50 // parse options set while parsing the module's header (init & del)
51 #define MOD_HEADER_PO (PO_LOCKDOWN & ~PO_NO_MODULES)
52 
53 // initial user module parse options
54 #define USER_MOD_PO (PO_NO_TOP_LEVEL_STATEMENTS | PO_REQUIRE_PROTOTYPES | PO_REQUIRE_OUR | PO_IN_MODULE)
55 
56 // module load options
57 #define QMLO_NONE 0
58 #define QMLO_INJECT (1 << 0)
59 #define QMLO_REINJECT (1 << 1)
60 #define QMLO_PRIVATE (1 << 2)
61 #define QMLO_RELOAD (1 << 3)
62 
64 hashdecl version_list_t : public std::vector<int> {
65 protected:
66  QoreString ver;
67 
68 public:
69  DLLLOCAL version_list_t() {
70  }
71 
72  DLLLOCAL version_list_t(const char* v) {
73  set(v);
74  }
75 
76  DLLLOCAL char set(const char* v);
77 
78  DLLLOCAL version_list_t& operator=(const char* v) {
79  set(v);
80  return *this;
81  }
82 
83  DLLLOCAL const char* operator*() const {
84  return ver.c_str();
85  }
86 };
87 
88 class QoreAbstractModule {
89 private:
90  // not implemented
91  DLLLOCAL QoreAbstractModule(const QoreAbstractModule&);
92  DLLLOCAL QoreAbstractModule& operator=(const QoreAbstractModule&);
93 
94 protected:
95  QoreString filename,
96  name,
97  desc,
98  author,
99  url,
100  license,
101  orig_name;
102 
103  // link to associated modules (originals with reinjection, etc)
104  QoreAbstractModule* prev = nullptr,
105  * next = nullptr;
106 
107  bool priv : 1,
108  injected : 1,
109  reinjected : 1;
110 
111  DLLLOCAL QoreHashNode* getHashIntern(bool with_filename = true) const;
112 
113  DLLLOCAL virtual void addToProgramImpl(QoreProgram* pgm, ExceptionSink& xsink) const = 0;
114 
115  DLLLOCAL void set(const char* d, const char* v, const char* a, const char* u, const QoreString& l) {
116  desc = d;
117  author = a;
118  url = u;
119  license = l;
120  version_list = v;
121  }
122 
123 public:
124  version_list_t version_list;
125  // list of dependent modules to reexport
126  name_vec_t rmod;
127 
128  // for binary modules
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) {
132  q_normalize_path(filename, cwd);
133  }
134 
135  // for user modules
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) {
139  q_normalize_path(filename, cwd);
140  }
141 
142  DLLLOCAL virtual ~QoreAbstractModule() {
143  //printd(5, "QoreAbstractModule::~QoreAbstractModule() this: %p name: %s\n", this, name.c_str());
144  if (next) {
145  assert(next->prev == this);
146  next->prev = prev;
147  }
148  if (prev) {
149  assert(prev->next == this);
150  prev->next = next;
151  }
152  }
153 
154  DLLLOCAL const char* getName() const {
155  return name.c_str();
156  }
157 
158  DLLLOCAL const char* getFileName() const {
159  return filename.c_str();
160  }
161 
162  DLLLOCAL const QoreString& getFileNameStr() const {
163  return filename;
164  }
165 
166  DLLLOCAL const char* getDesc() const {
167  return desc.c_str();
168  }
169 
170  DLLLOCAL const char* getVersion() const {
171  return* version_list;
172  }
173 
174  DLLLOCAL const char* getURL() const {
175  return url.c_str();
176  }
177 
178  DLLLOCAL const char* getOrigName() const {
179  return orig_name.empty() ? nullptr : orig_name.c_str();
180  }
181 
182  DLLLOCAL void resetName() {
183  assert(!orig_name.empty());
184  name = orig_name;
185  orig_name.clear();
186  }
187 
188  DLLLOCAL bool isInjected() const {
189  return injected;
190  }
191 
192  DLLLOCAL bool isReInjected() const {
193  return reinjected;
194  }
195 
196  DLLLOCAL void addModuleReExport(const char* m) {
197  rmod.push_back(m);
198  }
199 
200  DLLLOCAL void reexport(ExceptionSink& xsink, QoreProgram* pgm) const;
201 
202  DLLLOCAL void addToProgram(QoreProgram* pgm, ExceptionSink& xsink) const {
203  addToProgramImpl(pgm, xsink);
204  if (!xsink)
205  reexport(xsink, pgm);
206  }
207 
208  DLLLOCAL bool equalTo(const QoreAbstractModule* m) const {
209  assert(name == m->name);
210  return filename == m->filename;
211  }
212 
213  DLLLOCAL bool isPath(const char* p) const {
214  return filename == p;
215  }
216 
217  DLLLOCAL void rename(const QoreString& n) {
218  assert(orig_name.empty());
219  name = n;
220  }
221 
222  DLLLOCAL void setOrigName(const char* n) {
223  assert(orig_name.empty());
224  orig_name = n;
225  }
226 
227  DLLLOCAL bool isPrivate() const {
228  return priv;
229  }
230 
231  DLLLOCAL void setPrivate(bool p = true) {
232  assert(priv != p);
233  priv = p;
234  }
235 
236  DLLLOCAL void setLink(QoreAbstractModule* n) {
237  //printd(5, "AbstractQoreModule::setLink() n: %p '%s'\n", n, n->getName());
238  assert(!next);
239  assert(!n->prev);
240  next = n;
241  n->prev = this;
242  }
243 
244  DLLLOCAL QoreAbstractModule* getNext() const {
245  return next;
246  }
247 
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;
252 };
253 
254 // list/dequeue of strings
255 typedef std::deque<std::string> strdeque_t;
256 
258 
262 protected:
263  typedef std::set<std::string> strset_t;
264 
265  strdeque_t dlist;
266  strset_t dset;
267 
268 public:
269  DLLLOCAL void addDirList(const char* str);
270 
271  DLLLOCAL bool push_back(const std::string &str) {
272  if (dset.find(str) != dset.end()) {
273  return false;
274  }
275  dlist.push_back(str);
276  dset.insert(str);
277  return true;
278  }
279 
280  DLLLOCAL bool empty() const {
281  return dlist.empty();
282  }
283 
284  DLLLOCAL strdeque_t::const_iterator begin() const {
285  return dlist.begin();
286  }
287 
288  DLLLOCAL strdeque_t::const_iterator end() const {
289  return dlist.end();
290  }
291 
292  DLLLOCAL void appendPath(QoreString& str) const {
293  if (dlist.empty()) {
294  str.concat("<empty>");
295  return;
296  }
297  for (strdeque_t::const_iterator i = dlist.begin(), e = dlist.end(); i != e; ++i) {
298  str.concat((*i).c_str());
299  str.concat(':');
300  }
301  str.terminate(str.size() - 1);
302  }
303 };
304 
305 class QoreModuleContextHelper : public QoreModuleContext {
306 public:
307  DLLLOCAL QoreModuleContextHelper(const char* name, QoreProgram* pgm, ExceptionSink& xsink);
308  DLLLOCAL ~QoreModuleContextHelper();
309 };
310 
311 class QoreModuleDefContextHelper : public QoreModuleDefContext {
312 protected:
313  QoreModuleDefContext* old;
314 
315 public:
316  DLLLOCAL QoreModuleDefContextHelper() : old(set_module_def_context(this)) {
317  }
318 
319  DLLLOCAL ~QoreModuleDefContextHelper() {
320  set_module_def_context(old);
321  }
322 };
323 
324 class QoreUserModuleDefContextHelper;
325 class QoreUserModule;
326 
327 typedef std::set<std::string> strset_t;
328 typedef std::map<std::string, strset_t> md_map_t;
329 
330 class ModMap {
331 private:
332  DLLLOCAL ModMap(const ModMap &);
333  DLLLOCAL ModMap& operator=(const ModMap&);
334 
335 protected:
336  md_map_t map;
337 
338 public:
339  DLLLOCAL ModMap() {
340  }
341 
342  DLLLOCAL ~ModMap() {
343  }
344 
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())
350  return true;
351  i->second.insert(r);
352  return false;
353  }
354 
355  DLLLOCAL md_map_t::iterator begin() {
356  return map.begin();
357  }
358 
359  DLLLOCAL md_map_t::iterator end() {
360  return map.end();
361  }
362 
363  DLLLOCAL md_map_t::iterator find(const char* n) {
364  return map.find(n);
365  }
366 
367  DLLLOCAL md_map_t::iterator find(const std::string& n) {
368  return map.find(n);
369  }
370 
371  DLLLOCAL void erase(md_map_t::iterator i) {
372  map.erase(i);
373  }
374 
375  DLLLOCAL void clear() {
376  map.clear();
377  }
378 
379  DLLLOCAL bool empty() const {
380  return map.empty();
381  }
382 
383 #ifdef DEBUG
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) {
387  QoreString str("[");
388  for (strset_t::iterator si = i->second.begin(), se = i->second.end(); si != se; ++si)
389  str.sprintf("'%s',", (*si).c_str());
390  str.concat("]");
391 
392  printd(0, " + %s '%s' -> %s\n", name, i->first.c_str(), str.c_str());
393  }
394  }
395 #endif
396 };
397 
398 hashdecl DLHelper {
399  void* ptr;
400 
401  DLLLOCAL DLHelper(void* p) : ptr(p) {
402  }
403 
404  DLLLOCAL ~DLHelper() {
405  if (ptr)
406  dlclose(ptr);
407  }
408 
409  DLLLOCAL void* release() {
410  void* rv = ptr;
411  ptr = nullptr;
412  return rv;
413  }
414 };
415 
416 class QoreModuleManager {
417  friend class QoreAbstractModule;
418  friend class ModuleLoadMapHelper;
419 
420 public:
421  DLLLOCAL QoreModuleManager() {
422  }
423 
424  DLLLOCAL ~QoreModuleManager() {
425  }
426 
427  DLLLOCAL void init(bool se);
428  DLLLOCAL void delUser();
429  DLLLOCAL void cleanup();
430 
431  DLLLOCAL void issueParseCmd(const QoreProgramLocation* loc, const char* mname, const QoreString& cmd);
432 
433  DLLLOCAL void issueRuntimeCmd(const char* mname, QoreProgram* pgm, const QoreString& cmd, ExceptionSink* xsink);
434 
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));
438  //printd(5, "QoreModuleManager::addModule() m: %p '%s'\n", m, m->getName());
439  }
440 
441  DLLLOCAL QoreAbstractModule* findModule(const char* name) {
442  AutoLocker al(mutex);
443  return findModuleUnlocked(name);
444  }
445 
446  DLLLOCAL int parseLoadModule(ExceptionSink& xsink, ExceptionSink& wsink, const char* name, QoreProgram* pgm,
447  bool reexport = false);
448  DLLLOCAL int runTimeLoadModule(ExceptionSink& xsink, ExceptionSink& wsink, const char* name, QoreProgram* pgm,
449  QoreProgram* mpgm = nullptr, unsigned load_opt = QMLO_NONE, int warning_mask = QP_WARN_MODULES,
450  bool reexport = false, qore_binary_module_desc_t mod_desc_func = nullptr);
451 
452  DLLLOCAL QoreHashNode* getModuleHash();
453  DLLLOCAL QoreListNode* getModuleList();
454 
455  DLLLOCAL void addModuleDir(const char* dir) {
456  AutoLocker al(mutex);
457  moduleDirList.push_back(dir);
458  }
459 
460  DLLLOCAL void addModuleDirList(const char* strlist) {
461  AutoLocker al(mutex);
462  moduleDirList.addDirList(strlist);
463  }
464 
465  DLLLOCAL void addStandardModulePaths();
466 
467  DLLLOCAL void registerUserModuleFromSource(const char* name, const char* src, QoreProgram *pgm, ExceptionSink& xsink);
468 
469  DLLLOCAL void trySetUserModuleDependency(const QoreAbstractModule* mi) {
470  if (!mi->isUser())
471  return;
472 
473  const char* old_name = get_module_context_name();
474  if (old_name)
475  setUserModuleDependency(mi->getName(), old_name);
476  trySetUserModule(mi->getName());
477  }
478 
479  DLLLOCAL void trySetUserModule(const char* name) {
480  md_map_t::iterator i = md_map.find(name);
481  if (i == md_map.end()) {
482  umset.insert(name);
483  //printd(5, "QoreModuleManager::trySetUserModule('%s') UMSET SET: rmd_map: empty\n", name);
484  }
485 #ifdef DEBUG
486  /*
487  else {
488  QoreString str("[");
489  for (strset_t::iterator si = i->second.begin(), se = i->second.end(); si != se; ++si)
490  str.sprintf("'%s',", (*si).c_str());
491  str.concat("]");
492  //printd(5, "QoreModuleManager::trySetUserModule('%s') UMSET NOT SET: md_map: %s\n", name, str.c_str());
493  }
494  */
495 #endif
496  }
497 
498  DLLLOCAL void setUserModuleDependency(const char* name, const char* dep) {
499  //printd(5, "QoreModuleManager::setUserModuleDependency('%s' -> '%s')\n", name, dep);
500  if (md_map.addDep(name, dep))
501  return;
502  rmd_map.addDep(dep, name);
503 
504  strset_t::iterator ui = umset.find(name);
505  if (ui != umset.end()) {
506  umset.erase(ui);
507  //printd(5, "QoreModuleManager::setUserModuleDependency('%s' -> '%s') REMOVED '%s' FROM UMMSET\n", name, dep, name);
508  }
509  }
510 
511  DLLLOCAL void removeUserModuleDependency(const char* name, const char* orig_name = 0) {
512  //printd(5, "QoreModuleManager::removeUserModuleDependency() name: '%s' orig: '%s'\n", name, orig_name ? orig_name : "n/a");
513  md_map_t::iterator i = rmd_map.find(name);
514  if (i == rmd_map.end() && orig_name)
515  i = rmd_map.find(orig_name);
516  if (i != rmd_map.end()) {
517  // remove dependents
518  for (strset_t::iterator si = i->second.begin(), se = i->second.end(); si != se; ++si) {
519  md_map_t::iterator di = md_map.find(*si);
520  assert(di != md_map.end());
521 
522  strset_t::iterator dsi = di->second.find(i->first);
523  assert(dsi != di->second.end());
524  di->second.erase(dsi);
525  if (di->second.empty()) {
526  //printd(5, "QoreModuleManager::removeUserModuleDependency('%s') '%s' now empty, ADDING TO UMMSET: '%s'\n", name, i->first.c_str(), (*si).c_str());
527  //md_map.erase(di);
528  assert(umset.find(*si) == umset.end());
529  umset.insert(*si);
530  }
531  }
532  // remove from dep map
533  rmd_map.erase(i);
534  }
535 
536  i = md_map.find(name);
537  if (i != md_map.end())
538  md_map.erase(i);
539  if (orig_name) {
540  i = md_map.find(orig_name);
541  if (i != md_map.end())
542  md_map.erase(i);
543  }
544  }
545 
546 private:
547  // not implemented
548  DLLLOCAL QoreModuleManager(const QoreModuleManager&);
549  // not implemented
550  DLLLOCAL QoreModuleManager& operator=(const QoreModuleManager&);
552  DLLLOCAL QoreAbstractModule* loadSeparatedModule(
553  ExceptionSink& xsink,
554  ExceptionSink& wsink,
555  const char* path,
556  const char* feature,
557  QoreProgram* tpgm,
558  bool reexport = false,
559  QoreProgram* pgm = nullptr,
560  QoreProgram* path_pgm = nullptr,
561  unsigned load_opt = QMLO_NONE,
562  int warning_mask = QP_WARN_MODULES);
563 
564  typedef std::map<std::string, int> module_load_map_t;
565  QoreCondition module_load_cond;
566  // map feature names to TIDs when module initialization is in progress
567  module_load_map_t module_load_map;
568  // number of threads waiting on module_load_set
569  int module_load_waiting = 0;
570 
571 protected:
572  // mutex for atomicity
573  QoreThreadLock mutex;
574 
575  // user module dependency map: module -> dependents
576  ModMap md_map;
577  // user module dependent map: dependent -> module
578  ModMap rmd_map;
579 
580  // module blacklist
581  typedef std::map<const char*, const char*, ltstr> bl_map_t;
582  bl_map_t mod_blacklist;
583 
584  // module hash
585  typedef std::map<const char*, QoreAbstractModule*, ltstr> module_map_t;
586  module_map_t map;
587 
588  // set of user modules with no dependencies
589  strset_t umset;
590 
591  // list of module directories
592  UniqueDirectoryList moduleDirList;
593 
594  DLLLOCAL QoreAbstractModule* findModuleUnlocked(const char* name) {
595  module_map_t::iterator i = map.find(name);
596  return i == map.end() ? 0 : i->second;
597  }
598 
599  DLLLOCAL int loadModuleIntern(const char* name, QoreProgram* pgm, ExceptionSink& xsink) {
600  AutoLocker sl(mutex); // make sure checking and loading are atomic
601 
602  return loadModuleIntern(xsink, xsink, name, pgm);
603  }
604 
605  DLLLOCAL int loadModuleIntern(ExceptionSink& xsink, ExceptionSink& wsink, const char* name, QoreProgram* pgm,
606  bool reexport = false, mod_op_e op = MOD_OP_NONE, version_list_t* version = nullptr,
607  const char* src = nullptr, QoreProgram* mpgm = nullptr, unsigned load_opt = QMLO_NONE,
608  int warning_mask = QP_WARN_MODULES, qore_binary_module_desc_t mod_desc_func = nullptr);
609 
610  DLLLOCAL QoreAbstractModule* loadBinaryModuleFromPath(ExceptionSink& xsink, const char* path,
611  const char* feature = nullptr, QoreProgram* pgm = nullptr, bool reexport = false,
612  qore_binary_module_desc_t mod_desc = nullptr);
613 
614  DLLLOCAL QoreAbstractModule* loadBinaryModuleFromDesc(ExceptionSink& xsink, DLHelper* dlh,
615  QoreModuleInfo& mod_info, const char* path, const char* feature = nullptr, QoreProgram* pgm = nullptr,
616  bool reexport = false);
617 
618  DLLLOCAL QoreAbstractModule* loadUserModuleFromPath(ExceptionSink& xsink, ExceptionSink& wsink, const char* path,
619  const char* feature = nullptr, QoreProgram* tpgm = nullptr, bool reexport = false, QoreProgram* pgm = nullptr,
620  QoreProgram* path_pgm = nullptr, unsigned load_opt = QMLO_NONE, int warning_mask = QP_WARN_MODULES);
621 
622  DLLLOCAL QoreAbstractModule* loadUserModuleFromSource(ExceptionSink& xsink, ExceptionSink& wsink, const char* path,
623  const char* feature, QoreProgram* tpgm, const char* src, bool reexport, QoreProgram* pgm = nullptr,
624  int warning_mask = QP_WARN_MODULES);
625 
626  DLLLOCAL QoreAbstractModule* setupUserModule(ExceptionSink& xsink, std::unique_ptr<QoreUserModule>& mi,
627  QoreUserModuleDefContextHelper& qmd, unsigned load_opt = QMLO_NONE, int warning_mask = QP_WARN_MODULES);
628 
629  DLLLOCAL void reinjectModule(QoreAbstractModule* mi);
630  DLLLOCAL void delOrig(QoreAbstractModule* mi);
631  DLLLOCAL void getUniqueName(QoreString& nname, const char* name, const char* prefix);
632 };
633 
634 DLLLOCAL extern QoreModuleManager QMM;
635 
636 class QoreBuiltinModule : public QoreAbstractModule {
637 protected:
638  unsigned api_major, api_minor;
639  qore_module_init_t module_init;
640  qore_module_ns_init_t module_ns_init;
641  qore_module_delete_t module_delete;
642  qore_module_parse_cmd_t module_parse_cmd;
643  QoreHashNode* info;
644  const void* dlptr;
645 
646  DLLLOCAL virtual void addToProgramImpl(QoreProgram* pgm, ExceptionSink& xsink) const override;
647 
648 public:
649  DLLLOCAL QoreBuiltinModule(const char* cwd, const char* fn, const char* n, const char* d, const char* v,
650  const char* a, const char* u, const QoreString& l, unsigned major, unsigned minor, qore_module_init_t init,
651  qore_module_ns_init_t ns_init, qore_module_delete_t del, qore_module_parse_cmd_t pcmd, const void* p,
652  QoreHashNode* info = nullptr)
653  : QoreAbstractModule(cwd, fn, n, d, v, a, u, l), api_major(major), api_minor(minor), module_init(init),
654  module_ns_init(ns_init), module_delete(del), module_parse_cmd(pcmd), info(info), dlptr(p) {
655  }
656 
657  DLLLOCAL virtual ~QoreBuiltinModule() {
658  printd(5, "QoreBuiltinModule::~QoreBuiltinModule() '%s': %s calling module_delete: %p\n", name.c_str(),
659  filename.c_str(), module_delete);
660  module_delete();
661  // we do not close binary modules because we may have thread local data that needs to be
662  // destroyed when exit() is called
663  }
664 
665  DLLLOCAL unsigned getAPIMajor() const {
666  return api_major;
667  }
668 
669  DLLLOCAL unsigned getAPIMinor() const {
670  return api_minor;
671  }
672 
673  DLLLOCAL virtual bool isBuiltin() const override {
674  return true;
675  }
676 
677  DLLLOCAL virtual bool isUser() const override {
678  return false;
679  }
680 
681  DLLLOCAL QoreHashNode* getHash(bool with_filename = true) const override;
682 
683  DLLLOCAL const void* getPtr() const {
684  return dlptr;
685  }
686 
687  DLLLOCAL virtual void issueModuleCmd(const QoreProgramLocation* loc, const QoreString& cmd, ExceptionSink* xsink) override;
688 };
689 
690 class QoreUserModule : public QoreAbstractModule {
691 protected:
692  QoreProgram* pgm;
693  AbstractQoreNode* del = nullptr; // deletion closure / call reference
694 
695  DLLLOCAL virtual void addToProgramImpl(QoreProgram* pgm, ExceptionSink& xsink) const override;
696 
697 public:
698  DLLLOCAL QoreUserModule(const char* cwd, const char* fn, const char* n, QoreProgram* p, unsigned load_opt,
699  int warning_mask = QP_WARN_MODULES) : QoreAbstractModule(cwd, fn, n, load_opt), pgm(p) {
700  }
701 
702  DLLLOCAL void set(const char* d, const char* v, const char* a, const char* u, const QoreString& l, AbstractQoreNode* dl) {
703  QoreAbstractModule::set(d, v, a, u, l);
704  del = dl;
705  }
706 
707  DLLLOCAL QoreProgram* getProgram() const {
708  return pgm;
709  }
710 
711  DLLLOCAL virtual ~QoreUserModule();
712 
713  DLLLOCAL virtual bool isBuiltin() const override {
714  return false;
715  }
716 
717  DLLLOCAL virtual bool isUser() const override {
718  return true;
719  }
720 
721  DLLLOCAL virtual QoreHashNode* getHash(bool with_filename = true) const override {
722  return getHashIntern(with_filename);
723  }
724 
725  DLLLOCAL virtual void issueModuleCmd(const QoreProgramLocation* loc, const QoreString& cmd, ExceptionSink* xsink) override {
726  if (xsink) {
727  xsink->raiseException(*loc, "PARSE-COMMAND-ERROR", "module '%s' loaded from '%s' is a user module; only builtin modules can support parse commands",
728  name.c_str(), filename.c_str());
729  }
730  }
731 };
732 
733 class QoreModuleNameContextHelper {
734 public:
735  DLLLOCAL QoreModuleNameContextHelper(const char* name) : old_name(set_module_context_name(name)) {
736  }
737 
738  DLLLOCAL ~QoreModuleNameContextHelper() {
739  set_module_context_name(old_name);
740  }
741 
742 protected:
743  const char* old_name;
744 };
745 
746 class QoreUserModuleDefContextHelper : public QoreModuleDefContextHelper {
747 public:
748  DLLLOCAL QoreUserModuleDefContextHelper(const char* name, QoreProgram* p, ExceptionSink& xs);
749 
750  DLLLOCAL ~QoreUserModuleDefContextHelper() {
751  const char* name = set_module_context_name(old_name);
752 
753  if (xsink && !dup)
754  QMM.removeUserModuleDependency(name);
755  }
756 
757  DLLLOCAL void setDuplicate() {
758  assert(!dup);
759  dup = true;
760  }
761 
762  DLLLOCAL void setNameInit(const char* name);
763 
764  DLLLOCAL void close();
765 
766 protected:
767  const char* old_name;
768 
769  qore_program_private* pgm;
770  int64 po;
771 
772  ExceptionSink& xsink;
773  bool dup;
774 };
775 
776 class ModuleLoadMapHelper {
777 public:
778  DLLLOCAL ModuleLoadMapHelper(const char* feature);
779  DLLLOCAL ~ModuleLoadMapHelper();
780 
781 private:
782  QoreModuleManager::module_load_map_t::iterator i;
783 };
784 
785 #endif
void(* qore_module_ns_init_t)(QoreNamespace *root_ns, QoreNamespace *qore_ns)
signature of the module namespace change/delta function
Definition: ModuleManager.h:72
QoreStringNode *(* qore_module_init_t)()
signature of the module constructor/initialization function
Definition: ModuleManager.h:69
void(* qore_binary_module_desc_t)(QoreModuleInfo &mod_info)
Module description function.
Definition: ModuleManager.h:112
void(* qore_module_parse_cmd_t)(const QoreString &cmd, ExceptionSink *xsink)
signature of the module parse command function
Definition: ModuleManager.h:78
void(* qore_module_delete_t)()
signature of the module destructor function
Definition: ModuleManager.h:75
DLLEXPORT void q_normalize_path(QoreString &path, const char *cwd=0)
normalizes the given path for the current platform in place (makes absolute, removes "....
The base class for all value and parse types in Qore expression trees.
Definition: AbstractQoreNode.h:57
provides a safe and exception-safe way to hold locks in Qore, only to be used on the stack,...
Definition: QoreThreadLock.h:136
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:48
DLLEXPORT AbstractQoreNode * raiseException(const char *err, const char *fmt,...)
appends a Qore-language exception to the list
a thread condition class implementing a wrapper for pthread_cond_t
Definition: QoreCondition.h:45
This is the hash or associative list container type in Qore, dynamically allocated only,...
Definition: QoreHashNode.h:50
This is the list container type in Qore, dynamically allocated only, reference counted.
Definition: QoreListNode.h:52
supports parsing and executing Qore-language code, reference counted, dynamically-allocated only
Definition: QoreProgram.h:127
Qore's string type supported by the QoreEncoding class.
Definition: QoreString.h:93
DLLEXPORT void clear()
reset string to zero length; memory is not deallocated; string encoding does not change
DLLEXPORT void terminate(size_t size)
terminates the string at byte position "size", the string is reallocated if necessary
DLLEXPORT void concat(const QoreString *str, ExceptionSink *xsink)
concatenates a string and converts encodings if necessary
DLLEXPORT size_t size() const
returns number of bytes in the string (not including the null pointer)
DLLEXPORT bool empty() const
returns true if the string is empty, false if not
DLLEXPORT const char * c_str() const
returns the string's buffer; this data should not be changed
provides a mutually-exclusive thread lock
Definition: QoreThreadLock.h:49
non-thread-safe unique list of strings of directory names
Definition: ModuleInfo.h:261
std::vector< std::string > name_vec_t
vector of parameter names for parameter lists
Definition: common.h:257
long long int64
64bit integer type, cannot use int64_t here since it breaks the API on some 64-bit systems due to equ...
Definition: common.h:260
DLLEXPORT QoreProgram * getProgram()
returns the current QoreProgram
Qore module info.
Definition: ModuleManager.h:88
list of version numbers in order of importance (i.e. 1.2.3 = 1, 2, 3)
Definition: ModuleInfo.h:64