Qore Programming Language  0.9.16
ModuleInfo.h
1 /* -*- mode: c++; indent-tabs-mode: nil -*- */
2 /*
3  ModuleInfo.h
4 
5  Qore Programming Language
6 
7  Copyright (C) 2003 - 2020 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.getBuffer();
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.getBuffer());
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.getBuffer();
156  }
157 
158  DLLLOCAL const char* getFileName() const {
159  return filename.getBuffer();
160  }
161 
162  DLLLOCAL const QoreString& getFileNameStr() const {
163  return filename;
164  }
165 
166  DLLLOCAL const char* getDesc() const {
167  return desc.getBuffer();
168  }
169 
170  DLLLOCAL const char* getVersion() const {
171  return* version_list;
172  }
173 
174  DLLLOCAL const char* getURL() const {
175  return url.getBuffer();
176  }
177 
178  DLLLOCAL const char* getOrigName() const {
179  return orig_name.empty() ? 0 : orig_name.getBuffer();
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.getBuffer());
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  }
439 
440  DLLLOCAL QoreAbstractModule* findModule(const char* name) {
441  AutoLocker al(mutex);
442  return findModuleUnlocked(name);
443  }
444 
445  DLLLOCAL void parseLoadModule(ExceptionSink& xsink, ExceptionSink& wsink, const char* name, QoreProgram* pgm,
446  bool reexport = false);
447  DLLLOCAL int runTimeLoadModule(ExceptionSink& xsink, ExceptionSink& wsink, const char* name, QoreProgram* pgm,
448  QoreProgram* mpgm = nullptr, unsigned load_opt = QMLO_NONE, int warning_mask = QP_WARN_MODULES,
449  bool reexport = false, qore_binary_module_desc_t mod_desc_func = nullptr);
450 
451  DLLLOCAL QoreHashNode* getModuleHash();
452  DLLLOCAL QoreListNode* getModuleList();
453 
454  DLLLOCAL void addModuleDir(const char* dir) {
455  AutoLocker al(mutex);
456  moduleDirList.push_back(dir);
457  }
458 
459  DLLLOCAL void addModuleDirList(const char* strlist) {
460  AutoLocker al(mutex);
461  moduleDirList.addDirList(strlist);
462  }
463 
464  DLLLOCAL void addStandardModulePaths();
465 
466  DLLLOCAL void registerUserModuleFromSource(const char* name, const char* src, QoreProgram *pgm, ExceptionSink& xsink);
467 
468  DLLLOCAL void trySetUserModuleDependency(const QoreAbstractModule* mi) {
469  if (!mi->isUser())
470  return;
471 
472  const char* old_name = get_user_module_context_name();
473  if (old_name)
474  setUserModuleDependency(mi->getName(), old_name);
475  trySetUserModule(mi->getName());
476  }
477 
478  DLLLOCAL void trySetUserModule(const char* name) {
479  md_map_t::iterator i = md_map.find(name);
480  if (i == md_map.end()) {
481  umset.insert(name);
482  //printd(5, "QoreModuleManager::trySetUserModule('%s') UMSET SET: rmd_map: empty\n", name);
483  }
484 #ifdef DEBUG
485  /*
486  else {
487  QoreString str("[");
488  for (strset_t::iterator si = i->second.begin(), se = i->second.end(); si != se; ++si)
489  str.sprintf("'%s',", (*si).c_str());
490  str.concat("]");
491  //printd(5, "QoreModuleManager::trySetUserModule('%s') UMSET NOT SET: md_map: %s\n", name, str.getBuffer());
492  }
493  */
494 #endif
495  }
496 
497  DLLLOCAL void setUserModuleDependency(const char* name, const char* dep) {
498  //printd(5, "QoreModuleManager::setUserModuleDependency('%s' -> '%s')\n", name, dep);
499  if (md_map.addDep(name, dep))
500  return;
501  rmd_map.addDep(dep, name);
502 
503  strset_t::iterator ui = umset.find(name);
504  if (ui != umset.end()) {
505  umset.erase(ui);
506  //printd(5, "QoreModuleManager::setUserModuleDependency('%s' -> '%s') REMOVED '%s' FROM UMMSET\n", name, dep, name);
507  }
508  }
509 
510  DLLLOCAL void removeUserModuleDependency(const char* name, const char* orig_name = 0) {
511  //printd(5, "QoreModuleManager::removeUserModuleDependency() name: '%s' orig: '%s'\n", name, orig_name ? orig_name : "n/a");
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()) {
516  // remove dependents
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());
520 
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()) {
525  //printd(5, "QoreModuleManager::removeUserModuleDependency('%s') '%s' now empty, ADDING TO UMMSET: '%s'\n", name, i->first.c_str(), (*si).c_str());
526  //md_map.erase(di);
527  assert(umset.find(*si) == umset.end());
528  umset.insert(*si);
529  }
530  }
531  // remove from dep map
532  rmd_map.erase(i);
533  }
534 
535  i = md_map.find(name);
536  if (i != md_map.end())
537  md_map.erase(i);
538  if (orig_name) {
539  i = md_map.find(orig_name);
540  if (i != md_map.end())
541  md_map.erase(i);
542  }
543  }
544 
545 private:
546  // not implemented
547  DLLLOCAL QoreModuleManager(const QoreModuleManager&);
548  // not implemented
549  DLLLOCAL QoreModuleManager& operator=(const QoreModuleManager&);
551  DLLLOCAL QoreAbstractModule* loadSeparatedModule(
552  ExceptionSink& xsink,
553  ExceptionSink& wsink,
554  const QoreString& path,
555  const char* feature,
556  QoreProgram* tpgm,
557  bool reexport = false,
558  QoreProgram* pgm = nullptr,
559  QoreProgram* path_pgm = nullptr,
560  unsigned load_opt = QMLO_NONE,
561  int warning_mask = QP_WARN_MODULES);
562 
563  typedef std::map<std::string, int> module_load_map_t;
564  QoreCondition module_load_cond;
565  // map feature names to TIDs when module initialization is in progress
566  module_load_map_t module_load_map;
567  // number of threads waiting on module_load_set
568  int module_load_waiting = 0;
569 
570 protected:
571  // mutex for atomicity
572  QoreThreadLock mutex;
573 
574  // user module dependency map: module -> dependents
575  ModMap md_map;
576  // user module dependent map: dependent -> module
577  ModMap rmd_map;
578 
579  // module blacklist
580  typedef std::map<const char*, const char*, ltstr> bl_map_t;
581  bl_map_t mod_blacklist;
582 
583  // module hash
584  typedef std::map<const char*, QoreAbstractModule*, ltstr> module_map_t;
585  module_map_t map;
586 
587  // set of user modules with no dependencies
588  strset_t umset;
589 
590  // list of module directories
591  UniqueDirectoryList moduleDirList;
592 
593  DLLLOCAL QoreAbstractModule* findModuleUnlocked(const char* name) {
594  module_map_t::iterator i = map.find(name);
595  return i == map.end() ? 0 : i->second;
596  }
597 
598  DLLLOCAL void loadModuleIntern(const char* name, QoreProgram* pgm, ExceptionSink& xsink) {
599  AutoLocker sl(mutex); // make sure checking and loading are atomic
600 
601  loadModuleIntern(xsink, xsink, name, pgm);
602  }
603 
604  DLLLOCAL void loadModuleIntern(ExceptionSink& xsink, ExceptionSink& wsink, const char* name, QoreProgram* 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,
607  int warning_mask = QP_WARN_MODULES, qore_binary_module_desc_t mod_desc_func = nullptr);
608 
609  DLLLOCAL QoreAbstractModule* loadBinaryModuleFromPath(ExceptionSink& xsink, const char* path,
610  const char* feature = nullptr, QoreProgram* pgm = nullptr, bool reexport = false,
611  qore_binary_module_desc_t mod_desc = nullptr);
612 
613  DLLLOCAL QoreAbstractModule* loadBinaryModuleFromDesc(ExceptionSink& xsink, DLHelper* dlh,
614  QoreModuleInfo& mod_info, const char* path, const char* feature = nullptr, QoreProgram* pgm = nullptr,
615  bool reexport = false);
616 
617  DLLLOCAL QoreAbstractModule* loadUserModuleFromPath(ExceptionSink& xsink, ExceptionSink& wsink, const char* path,
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);
620 
621  DLLLOCAL QoreAbstractModule* loadUserModuleFromSource(ExceptionSink& xsink, ExceptionSink& wsink, const char* path,
622  const char* feature, QoreProgram* tpgm, const char* src, bool reexport, QoreProgram* pgm = nullptr,
623  int warning_mask = QP_WARN_MODULES);
624 
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);
627 
628  DLLLOCAL void reinjectModule(QoreAbstractModule* mi);
629  DLLLOCAL void delOrig(QoreAbstractModule* mi);
630  DLLLOCAL void getUniqueName(QoreString& nname, const char* name, const char* prefix);
631 };
632 
633 DLLLOCAL extern QoreModuleManager QMM;
634 
635 class QoreBuiltinModule : public QoreAbstractModule {
636 protected:
637  unsigned api_major, api_minor;
638  qore_module_init_t module_init;
639  qore_module_ns_init_t module_ns_init;
640  qore_module_delete_t module_delete;
641  qore_module_parse_cmd_t module_parse_cmd;
642  QoreHashNode* info;
643  const void* dlptr;
644 
645  DLLLOCAL virtual void addToProgramImpl(QoreProgram* pgm, ExceptionSink& xsink) const override;
646 
647 public:
648  DLLLOCAL QoreBuiltinModule(const char* cwd, const char* fn, const char* n, const char* d, const char* v,
649  const char* a, const char* u, const QoreString& l, unsigned major, unsigned minor, qore_module_init_t init,
650  qore_module_ns_init_t ns_init, qore_module_delete_t del, qore_module_parse_cmd_t pcmd, const void* p,
651  QoreHashNode* info = nullptr)
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) {
654  }
655 
656  DLLLOCAL virtual ~QoreBuiltinModule() {
657  printd(5, "QoreBuiltinModule::~QoreBuiltinModule() '%s': %s calling module_delete: %p\n", name.getBuffer(), filename.getBuffer(), module_delete);
658  module_delete();
659  // we do not close binary modules because we may have thread local data that needs to be
660  // destroyed when exit() is called
661  }
662 
663  DLLLOCAL unsigned getAPIMajor() const {
664  return api_major;
665  }
666 
667  DLLLOCAL unsigned getAPIMinor() const {
668  return api_minor;
669  }
670 
671  DLLLOCAL virtual bool isBuiltin() const override {
672  return true;
673  }
674 
675  DLLLOCAL virtual bool isUser() const override {
676  return false;
677  }
678 
679  DLLLOCAL QoreHashNode* getHash(bool with_filename = true) const override;
680 
681  DLLLOCAL const void* getPtr() const {
682  return dlptr;
683  }
684 
685  DLLLOCAL virtual void issueModuleCmd(const QoreProgramLocation* loc, const QoreString& cmd, ExceptionSink* xsink) override;
686 };
687 
688 class QoreUserModule : public QoreAbstractModule {
689 protected:
690  QoreProgram* pgm;
691  AbstractQoreNode* del = nullptr; // deletion closure / call reference
692 
693  DLLLOCAL virtual void addToProgramImpl(QoreProgram* pgm, ExceptionSink& xsink) const override;
694 
695 public:
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) {
698  }
699 
700  DLLLOCAL void set(const char* d, const char* v, const char* a, const char* u, const QoreString& l, AbstractQoreNode* dl) {
701  QoreAbstractModule::set(d, v, a, u, l);
702  del = dl;
703  }
704 
705  DLLLOCAL QoreProgram* getProgram() const {
706  return pgm;
707  }
708 
709  DLLLOCAL virtual ~QoreUserModule();
710 
711  DLLLOCAL virtual bool isBuiltin() const override {
712  return false;
713  }
714 
715  DLLLOCAL virtual bool isUser() const override {
716  return true;
717  }
718 
719  DLLLOCAL virtual QoreHashNode* getHash(bool with_filename = true) const override {
720  return getHashIntern(with_filename);
721  }
722 
723  DLLLOCAL virtual void issueModuleCmd(const QoreProgramLocation* loc, const QoreString& cmd, ExceptionSink* xsink) override {
724  if (xsink) {
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());
727  }
728  }
729 };
730 
731 class QoreUserModuleDefContextHelper : public QoreModuleDefContextHelper {
732 public:
733  DLLLOCAL QoreUserModuleDefContextHelper(const char* name, QoreProgram* p, ExceptionSink& xs);
734 
735  DLLLOCAL ~QoreUserModuleDefContextHelper() {
736  const char* name = set_user_module_context_name(old_name);
737 
738  if (xsink && !dup)
739  QMM.removeUserModuleDependency(name);
740  }
741 
742  DLLLOCAL void setDuplicate() {
743  assert(!dup);
744  dup = true;
745  }
746 
747  DLLLOCAL void setNameInit(const char* name);
748 
749  DLLLOCAL void close();
750 
751 protected:
752  const char* old_name;
753 
754  qore_program_private* pgm;
755  int64 po;
756 
757  ExceptionSink& xsink;
758  bool dup;
759 };
760 
761 class ModuleLoadMapHelper {
762 public:
763  DLLLOCAL ModuleLoadMapHelper(const char* feature);
764  DLLLOCAL ~ModuleLoadMapHelper();
765 
766 private:
767  QoreModuleManager::module_load_map_t::iterator i;
768 };
769 
770 #endif
qore_module_parse_cmd_t
void(* qore_module_parse_cmd_t)(const QoreString &cmd, ExceptionSink *xsink)
signature of the module parse command function
Definition: ModuleManager.h:78
qore_module_ns_init_t
void(* qore_module_ns_init_t)(QoreNamespace *root_ns, QoreNamespace *qore_ns)
signature of the module namespace change/delta function
Definition: ModuleManager.h:72
QoreString::clear
DLLEXPORT void clear()
reset string to zero length; memory is not deallocated; string encoding does not change
QoreString::size
DLLEXPORT qore_size_t size() const
returns number of bytes in the string (not including the null pointer)
QoreProgram
supports parsing and executing Qore-language code, reference counted, dynamically-allocated only
Definition: QoreProgram.h:126
QoreHashNode
This is the hash or associative list container type in Qore, dynamically allocated only,...
Definition: QoreHashNode.h:50
UniqueDirectoryList
non-thread-safe unique list of strings of directory names
Definition: ModuleInfo.h:261
version_list_t
list of version numbers in order of importance (i.e. 1.2.3 = 1, 2, 3)
Definition: ModuleInfo.h:64
QoreListNode
This is the list container type in Qore, dynamically allocated only, reference counted.
Definition: QoreListNode.h:52
QoreCondition
a thread condition class implementing a wrapper for pthread_cond_t
Definition: QoreCondition.h:45
int64
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
AutoLocker
provides a safe and exception-safe way to hold locks in Qore, only to be used on the stack,...
Definition: QoreThreadLock.h:136
QoreString
Qore's string type supported by the QoreEncoding class.
Definition: QoreString.h:81
QoreString::c_str
const DLLEXPORT char * c_str() const
returns the string's buffer; this data should not be changed
ExceptionSink::raiseException
DLLEXPORT AbstractQoreNode * raiseException(const char *err, const char *fmt,...)
appends a Qore-language exception to the list
QoreString::terminate
DLLEXPORT void terminate(qore_size_t size)
terminates the string at byte position "size", the string is reallocated if necessary
QoreModuleInfo
Qore module info.
Definition: ModuleManager.h:88
QoreString::getBuffer
const DLLEXPORT char * getBuffer() const
returns the string's buffer; this data should not be changed
QoreString::concat
DLLEXPORT void concat(const QoreString *str, ExceptionSink *xsink)
concatenates a string and converts encodings if necessary
ExceptionSink
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:48
qore_module_delete_t
void(* qore_module_delete_t)()
signature of the module destructor function
Definition: ModuleManager.h:75
QoreThreadLock
provides a mutually-exclusive thread lock
Definition: QoreThreadLock.h:49
qore_binary_module_desc_t
void(* qore_binary_module_desc_t)(QoreModuleInfo &mod_info)
Module description function.
Definition: ModuleManager.h:112
qore_module_init_t
QoreStringNode *(* qore_module_init_t)()
signature of the module constructor/initialization function
Definition: ModuleManager.h:69
QoreString::empty
DLLEXPORT bool empty() const
returns true if the string is empty, false if not
getProgram
DLLEXPORT QoreProgram * getProgram()
returns the current QoreProgram
name_vec_t
std::vector< std::string > name_vec_t
vector of parameter names for parameter lists
Definition: common.h:257
AbstractQoreNode
The base class for all value and parse types in Qore expression trees.
Definition: AbstractQoreNode.h:54
q_normalize_path
DLLEXPORT void q_normalize_path(QoreString &path, const char *cwd=0)
normalizes the given path for the current platform in place (makes absolute, removes "....