Qore Programming Language  0.9.16
QoreLibIntern.h
1 /* -*- mode: c++; indent-tabs-mode: nil -*- */
2 /*
3  QoreLibIntern.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_QORELIBINTERN_H
33 
34 #define _QORE_QORELIBINTERN_H
35 
36 #include "qore/intern/config.h"
37 
38 #include <atomic>
39 #include <cstdarg>
40 #include <sys/types.h>
41 
42 #ifdef HAVE_SYS_STATVFS_H
43 #define Q_HAVE_STATVFS
44 #include <sys/statvfs.h>
45 #endif
46 #include <sys/stat.h>
47 #include <unistd.h>
48 #ifdef HAVE_EXECINFO_H
49 #include <execinfo.h>
50 #endif
51 #ifdef HAVE_ARPA_INET_H
52 #include <arpa/inet.h>
53 #endif
54 #ifdef HAVE_SYS_SOCKET_H
55 #include <sys/socket.h>
56 #endif
57 #ifdef HAVE_NETDB_H
58 #include <netdb.h>
59 #endif
60 #ifdef HAVE_NETINET_IN_H
61 #include <netinet/in.h>
62 #endif
63 #ifdef HAVE_ARPA_INET_H
64 #include <arpa/inet.h>
65 #endif
66 #ifdef HAVE_SYS_SOCKET_H
67 #include <sys/socket.h>
68 #endif
69 #ifdef HAVE_NETDB_H
70 #include <netdb.h>
71 #endif
72 #ifdef HAVE_ARPA_INET_H
73 #include <arpa/inet.h>
74 #endif
75 #ifdef HAVE_WINSOCK2_H
76 #include <winsock2.h>
77 #endif
78 #ifdef HAVE_WS2TCPIP_H
79 #include <ws2tcpip.h>
80 #endif
81 #ifdef HAVE_SYS_UN_H
82 #include <sys/un.h>
83 #endif
84 #ifdef HAVE_NETINET_TCP_H
85 #include <netinet/tcp.h>
86 #endif
87 
88 #ifdef HAVE_STDINT_H
89 #include <stdint.h>
90 #endif
91 #ifdef HAVE_INTTYPES_H
92 #include <cinttypes>
93 #endif
94 
95 #ifndef HAVE_STRCASESTR
96 extern char* strcasestr(const char* s1, const char* s2);
97 #endif
98 
99 // make sure that intmax support is available from mpfr
100 #define MPFR_USE_INTMAX_T 1
101 
102 // for arbitrary-precision numeric support
103 #include <mpfr.h>
104 
105 // printf format for size_t or qore_size_t integers
106 #if TARGET_BITS == 64
107 #define QSD QLLD
108 #else
109 #define QSD "%d"
110 #endif
111 
112 #include <set>
113 #include <list>
114 #include <map>
115 #include <vector>
116 
117 // here we define virtual types
118 #define NT_NONE -1
119 #define NT_ALL -2
120 #define NT_CODE -3
121 #define NT_SOFTINT -4
122 #define NT_SOFTFLOAT -5
123 #define NT_SOFTNUMBER -6
124 #define NT_SOFTBOOLEAN -7
125 #define NT_SOFTSTRING -8
126 #define NT_SOFTDATE -9
127 #define NT_SOFTLIST -10
128 #define NT_TIMEOUT -11
129 #define NT_INTORFLOAT -12
130 #define NT_INTFLOATORNUMBER -13
131 #define NT_FLOATORNUMBER -14
132 #define NT_SOFTBINARY -15
133 
134 #define NT_SOMETHING -101 // i.e. "not NOTHING"
135 #define NT_DATA -102 // either QoreStringNode or BinaryNode
136 
137 typedef std::set<QoreObject*> obj_set_t;
138 
139 // issue #3818: Qore SSL app-specific data index
140 DLLLOCAL extern int qore_ssl_data_index;
141 
143 enum q_setpub_t : unsigned char {
144  CSP_UNCHANGED = 0,
145  CSP_SETPRIV = 1,
146  CSP_SETPUB = 2,
147 };
148 
149 DLLLOCAL void parse_init_value(QoreValue& val, LocalVar* oflag, int pflag, int& lvids, const QoreTypeInfo*& typeInfo);
150 
151 // since Qore 0.9.5
152 DLLLOCAL QoreValue q_call_static_method_args(QoreProgram* pgm, const QoreStringNode* class_name, const QoreStringNode* method, const QoreListNode* args, ExceptionSink* xsink);
153 
154 // returns true if the node needs to be scanned for recursive references or not
155 DLLLOCAL bool needs_scan(const AbstractQoreNode* n);
156 DLLLOCAL bool needs_scan(const QoreValue& v);
157 // increments or decrements the object count depending on the sign of the argument (cannot be 0)
158 DLLLOCAL void inc_container_obj(const AbstractQoreNode* n, int dt);
159 
160 DLLLOCAL AbstractQoreNode* missing_openssl_feature(const char* f, ExceptionSink* xsink);
161 
162 hashdecl ParseWarnOptions {
163  int64 parse_options;
164  int warn_mask;
165 
166  DLLLOCAL ParseWarnOptions() : parse_options(0), warn_mask(0) {
167  }
168 
169  DLLLOCAL ParseWarnOptions(int64 n_parse_options, int n_warn_mask = 0) : parse_options(n_parse_options), warn_mask(n_warn_mask) {
170  }
171 
172  DLLLOCAL void operator=(const ParseWarnOptions& pwo) {
173  parse_options = pwo.parse_options;
174  warn_mask = pwo.warn_mask;
175  }
176 
177  DLLLOCAL bool operator==(const ParseWarnOptions& pwo) const {
178  return parse_options == pwo.parse_options && warn_mask == pwo.warn_mask;
179  }
180 };
181 
182 hashdecl QoreProgramLineLocation {
183  int16_t start_line = -1,
184  end_line = -1;
185 
186  // if sline is 0 and eline is > 0 then set sline to 1
187  DLLLOCAL QoreProgramLineLocation(int sline, int eline) : start_line(sline ? sline : (eline ? 1 : 0)), end_line(eline) {
188  assert(sline <= 0xffff);
189  assert(eline <= 0xffff);
190  }
191 
192  DLLLOCAL QoreProgramLineLocation() {
193  }
194 
195  DLLLOCAL QoreProgramLineLocation(const QoreProgramLineLocation& old) = default;
196 
197  DLLLOCAL QoreProgramLineLocation(QoreProgramLineLocation&& old) = default;
198 };
199 
200 hashdecl QoreProgramLocation : public QoreProgramLineLocation {
201 public:
202  // "blank" constructor
203  DLLLOCAL QoreProgramLocation() {
204  }
205 
206  DLLLOCAL explicit QoreProgramLocation(const char* f, int sline, int eline, const char* source, int offset,
207  const char* lang = "Qore") :
208  QoreProgramLineLocation(sline, eline), file(f), source(source), lang(lang), offset(offset) {
209  assert(offset <= 0xffff);
210  }
211 
212  DLLLOCAL explicit QoreProgramLocation(const char* f, int sline = 0, int eline = 0) :
213  QoreProgramLineLocation(sline, eline), file(f) {
214  }
215 
216  // sets file position info from thread-local parse information
217  DLLLOCAL QoreProgramLocation(int sline, int eline);
218 
219  DLLLOCAL QoreProgramLocation(const QoreProgramLocation& old) = default;
220 
221  DLLLOCAL QoreProgramLocation(QoreProgramLocation&& old) = default;
222 
223  DLLLOCAL void clear() {
224  start_line = end_line = -1;
225  file = nullptr;
226  source = nullptr;
227  offset = 0;
228  }
229 
230  DLLLOCAL void toString(QoreString& str) const;
231 
232  DLLLOCAL const char* getFile() const {
233  return file;
234  }
235 
236  DLLLOCAL const char* getFileValue() const {
237  return file ? file : "";
238  }
239 
240  DLLLOCAL const char* getSource() const {
241  return source;
242  }
243 
244  DLLLOCAL const char* getSourceValue() const {
245  return source ? source : "";
246  }
247 
248  DLLLOCAL const char* getLanguage() const {
249  return lang;
250  }
251 
252  DLLLOCAL const char* getLanguageValue() const {
253  return lang ? lang : "";
254  }
255 
256  DLLLOCAL void setFile(const char* f) {
257  file = f;
258  }
259 
260  DLLLOCAL void setSource(const char* s) {
261  source = s;
262  }
263 
264  DLLLOCAL void setLanguage(const char* l) {
265  lang = l;
266  }
267 
268  DLLLOCAL bool operator<(const QoreProgramLocation& loc) const {
269  return start_line < loc.start_line
270  || end_line < loc.end_line
271  || file < loc.file
272  || source < loc.source
273  || offset < loc.offset
274  || lang < loc.lang;
275  }
276 
277  DLLLOCAL bool operator==(const QoreProgramLocation& loc) const {
278  return start_line == loc.start_line
279  && end_line == loc.end_line
280  && file == loc.file
281  && source == loc.source
282  && offset == loc.offset
283  && lang == loc.lang;
284  }
285 
286  DLLLOCAL bool operator!=(const QoreProgramLocation& loc) const {
287  return !(*this == loc);
288  }
289 
290 protected:
291  const char* file = nullptr;
292  const char* source = nullptr;
293  const char* lang = "Qore";
294 
295 public:
296  int16_t offset = 0;
297 };
298 
299 DLLLOCAL extern const QoreProgramLocation loc_builtin;
300 
301 hashdecl QoreCommandLineLocation : public QoreProgramLocation {
302  DLLLOCAL QoreCommandLineLocation() : QoreProgramLocation("<command-line>", 1, 1) {
303  }
304 };
305 
306 // parse location for objects parsed on the command-line
307 DLLLOCAL extern QoreCommandLineLocation qoreCommandLineLocation;
308 
309 // the following functions are implemented in support.cpp
310 DLLLOCAL void parse_error(const QoreProgramLocation& loc, const char* fmt, ...);
311 DLLLOCAL void parseException(const QoreProgramLocation& loc, const char* err, const char* fmt, ...);
312 DLLLOCAL void parseException(const QoreProgramLocation& loc, const char* err, QoreStringNode* desc);
313 
314 DLLLOCAL QoreString* findFileInPath(const char* file, const char* path);
315 DLLLOCAL QoreString* findFileInEnvPath(const char* file, const char* varname);
316 DLLLOCAL int qore_find_file_in_path(QoreString& str, const char* file, const char* path);
317 
318 DLLLOCAL const QoreTypeInfo* getBuiltinUserTypeInfo(const char* str);
319 DLLLOCAL const QoreTypeInfo* getBuiltinUserOrNothingTypeInfo(const char* str);
320 //DLLLOCAL qore_type_t getBuiltinType(const char* str);
321 DLLLOCAL const char* getBuiltinTypeName(qore_type_t type);
322 
323 // processes parameter information
324 DLLLOCAL void qore_process_params(unsigned num_params, type_vec_t& typeList, arg_vec_t& defaultArgList, va_list args);
325 DLLLOCAL void qore_process_params(unsigned num_params, type_vec_t& typeList, arg_vec_t& defaultArgList, name_vec_t& nameList, va_list args);
326 
327 // call to get a node with reference count 1 (copy on write)
328 void ensure_unique(AbstractQoreNode** v, ExceptionSink* xsink);
329 void ensure_unique(QoreValue& v, ExceptionSink* xsink);
330 
331 #ifndef HAVE_ATOLL
332 #ifdef HAVE_STRTOIMAX
333 static inline long long atoll(const char* str) {
334  return strtoimax(str, 0, 10);
335 }
336 #else
337 static inline long long atoll(const char* str) {
338  long long i;
339  sscanf(str, "%lld", &i);
340  return i;
341 }
342 #endif
343 #endif
344 
345 #if !defined(HAVE_STRTOLL) && defined(HAVE_STRTOIMAX)
346 #include <cinttypes>
347 #define strtoll strtoimax
348 #endif
349 
350 // use umem for memory allocation if available
351 #ifdef HAVE_UMEM_H
352 #include <umem.h>
353 #endif
354 
355 #ifdef HAVE_OPENSSL_CONST
356 #define OPENSSL_CONST const
357 #else
358 #define OPENSSL_CONST
359 #endif
360 
361 #ifdef HAVE_X509_GET0_SIGNATURE_CONST
362 #define OPENSSL_X509_GET0_SIGNATURE_CONST const
363 #else
364 #define OPENSSL_X509_GET0_SIGNATURE_CONST
365 #endif
366 
367 typedef std::set<const AbstractQoreNode*> const_node_set_t;
368 typedef std::set<LocalVar*> lvar_set_t;
369 
370 class LVarSet : public lvar_set_t {
371 protected:
372  // true if at least one variable in the set could contain an object or a closure (also through a container)
373  bool needs_scan;
374 
375 public:
376  // creates the object
377  DLLLOCAL LVarSet() : needs_scan(false) {
378  }
379 
380  // adds a local variable to the set
381  DLLLOCAL void add(LocalVar* var);
382 
383  // returns true if at least one variable in the set could contain an object or a closure (also through a container)
384  DLLLOCAL bool needsScan() const {
385  return needs_scan;
386  }
387 };
388 
389 enum obe_type_e { OBE_Unconditional, OBE_Success, OBE_Error };
390 
391 class StatementBlock;
392 typedef std::pair<enum obe_type_e, StatementBlock*> qore_conditional_block_exit_statement_t;
393 
394 typedef std::list<qore_conditional_block_exit_statement_t> block_list_t;
395 
396 // for maps of thread condition variables to TIDs
397 typedef std::map<QoreCondition*, int> cond_map_t;
398 
399 #if defined(HAVE_CHECK_STACK_POS)
400 #define QORE_MANAGE_STACK
401 #endif
402 
403 // Datasource Access Helper codes
404 #define DAH_NOCHANGE 0 // acquire lock temporarily
405 #define DAH_ACQUIRE 1 // acquire lock and hold
406 #define DAH_RELEASE 2 // release lock at end of action
407 #define DAH_NOCONN 3 // acquire lock temporarily and do not make a connection
408 
409 #define DAH_TEXT(d) (d == DAH_RELEASE ? "RELEASE" : (d == DAH_ACQUIRE ? "ACQUIRE" : "NOCHANGE"))
410 
411 DLLLOCAL int check_lvalue(QoreValue n, bool assign = true);
412 DLLLOCAL int check_lvalue(AbstractQoreNode* n, bool assign = true);
413 DLLLOCAL int check_lvalue_int(const QoreProgramLocation* loc, const QoreTypeInfo*& typeInfo, const char* name);
414 DLLLOCAL int check_lvalue_float(const QoreProgramLocation* loc, const QoreTypeInfo*& typeInfo, const char* name);
415 DLLLOCAL int check_lvalue_int_float_number(const QoreProgramLocation* loc, const QoreTypeInfo*& typeInfo, const char* name);
416 DLLLOCAL int check_lvalue_number(const QoreProgramLocation* loc, const QoreTypeInfo*& typeInfo, const char* name);
417 
418 DLLLOCAL extern QoreClass* QC_PSEUDOVALUE;
419 DLLLOCAL extern QoreClass* QC_PSEUDONOTHING;
420 
421 DLLLOCAL bool node_has_effect(const AbstractQoreNode* n);
422 
423 DLLLOCAL QoreString* q_fix_decimal(QoreString* str, size_t offset);
424 DLLLOCAL QoreStringNode* q_fix_decimal(QoreStringNode* str, size_t offset);
425 
426 #ifdef _Q_WINDOWS
427 // simulated block size for statvfs() on Windows
428 #define Q_SVF_BSIZE 4096
429 #define Q_HAVE_STATVFS
430 hashdecl statvfs {
431  unsigned long f_bsize; /* File system block size */
432  unsigned long f_frsize; /* Fundamental file system block size */
433  unsigned int f_blocks; /* Blocks on FS in units of f_frsize */
434  unsigned int f_bfree; /* Free blocks */
435  unsigned int f_bavail; /* Blocks available to non-root */
436  unsigned int f_files; /* Total inodes */
437  unsigned int f_ffree; /* Free inodes */
438  unsigned int f_favail; /* Free inodes for non-root */
439  unsigned long f_fsid; /* Filesystem ID */
440  unsigned long f_flag; /* Bit mask of values */
441  unsigned long f_namemax; /* Max file name length */
442 
443  DLLLOCAL void set(int64 avail, int64 total, int64 free) {
444  f_frsize = f_bsize = Q_SVF_BSIZE;
445  f_blocks = total / Q_SVF_BSIZE;
446  f_bfree = free / Q_SVF_BSIZE;
447  f_bavail = avail / Q_SVF_BSIZE;
448  // simulate inodes
449  f_files = f_blocks / 8;
450  f_ffree = f_bfree / 8;
451  f_favail = f_bavail / 8;
452  f_fsid = 0;
453  f_flag = 0;
454  f_namemax = 256;
455  }
456 };
457 DLLLOCAL int statvfs(const char* path, struct statvfs* buf);
458 DLLLOCAL int q_fstatvfs(const char* filepath, struct statvfs* buf);
459 #endif
460 
463 public:
464  DLLLOCAL SafeDerefHelper(ExceptionSink* xsink) : xsink(xsink) {
465  }
466 
468  DLLLOCAL ~SafeDerefHelper() {
469  if (value_list) {
470  for (auto& i : *value_list) {
471  i.discard(xsink);
472  }
473  delete value_list;
474  }
475  }
476 
478  DLLLOCAL void deref(QoreValue v) {
479  if (v.derefCanThrowException()) {
480  add(v);
481  } else {
482  v.discard(nullptr);
483  }
484  }
485 
487  DLLLOCAL void add(QoreValue v) {
488  if (!value_list) {
489  value_list = new arg_vec_t;
490  }
491  value_list->push_back(v);
492  }
493 
494 protected:
495  ExceptionSink* xsink;
496  arg_vec_t* value_list = nullptr;
497 };
498 
499 class QoreParseListNode;
500 
501 #include "qore/intern/NamedScope.h"
502 #include "qore/intern/QoreTypeInfo.h"
503 #include "qore/intern/ParseNode.h"
504 #include "qore/intern/QoreThreadList.h"
505 #include "qore/intern/lvalue_ref.h"
506 #include "qore/intern/qore_thread_intern.h"
507 #include "qore/intern/Function.h"
508 #include "qore/intern/CallReferenceCallNode.h"
509 #include "qore/intern/CallReferenceNode.h"
510 #include "qore/intern/BuiltinFunction.h"
511 #include "qore/intern/AbstractStatement.h"
512 #include "qore/intern/Variable.h"
513 #include "qore/intern/LocalVar.h"
514 #include "qore/intern/ScopedObjectCallNode.h"
515 #include "qore/intern/NewComplexTypeNode.h"
516 #include "qore/intern/ScopedRefNode.h"
517 #include "qore/intern/ClassRefNode.h"
518 #include "qore/intern/Context.h"
519 #include "qore/intern/BarewordNode.h"
520 #include "qore/intern/SelfVarrefNode.h"
521 #include "qore/intern/StaticClassVarRefNode.h"
522 #include "qore/intern/BackquoteNode.h"
523 #include "qore/intern/ContextrefNode.h"
524 #include "qore/intern/ContextRowNode.h"
525 #include "qore/intern/ComplexContextrefNode.h"
526 #include "qore/intern/FindNode.h"
527 #include "qore/intern/VRMutex.h"
528 #include "qore/intern/VLock.h"
529 #include "qore/intern/QoreException.h"
530 #include "qore/intern/StatementBlock.h"
531 #include "qore/intern/VarRefNode.h"
532 #include "qore/intern/QoreRegexSubst.h"
533 #include "qore/intern/QoreRegex.h"
534 #include "qore/intern/QoreTransliteration.h"
535 #include "qore/intern/ObjectMethodReferenceNode.h"
536 #include "qore/intern/QoreClosureParseNode.h"
537 #include "qore/intern/QoreClosureNode.h"
538 #include "qore/intern/QoreImplicitArgumentNode.h"
539 #include "qore/intern/QoreImplicitElementNode.h"
540 #include "qore/intern/QoreOperatorNode.h"
541 #include "qore/intern/QoreTimeZoneManager.h"
542 #include "qore/intern/ContextStatement.h"
543 #include "qore/intern/SwitchStatement.h"
544 #include "qore/intern/QorePseudoMethods.h"
545 #include "qore/intern/ParseReferenceNode.h"
546 #include "qore/intern/WeakReferenceNode.h"
547 
548 DLLLOCAL extern std::atomic<bool> qore_initialized;
549 DLLLOCAL extern std::atomic<bool> qore_shutdown;
550 DLLLOCAL extern std::atomic<bool> qore_exiting;
551 
552 DLLLOCAL extern int qore_library_options;
553 
554 #ifndef HAVE_GETHOSTBYADDR_R
555 DLLLOCAL extern QoreThreadLock lck_gethostbyaddr;
556 #endif
557 
558 DLLLOCAL extern qore_license_t qore_license;
559 
560 #ifndef NET_BUFSIZE
561 #define NET_BUFSIZE 1024
562 #endif
563 
564 #ifndef HOSTNAMEBUFSIZE
565 #define HOSTNAMEBUFSIZE 512
566 #endif
567 
568 #ifndef HAVE_LOCALTIME_R
569 DLLLOCAL extern QoreThreadLock lck_localtime;
570 #endif
571 
572 #ifndef HAVE_GMTIME_R
573 DLLLOCAL extern QoreThreadLock lck_gmtime;
574 #endif
575 
576 DLLLOCAL extern char table64[64];
577 
578 DLLLOCAL int get_nibble(char c, ExceptionSink* xsink);
579 DLLLOCAL BinaryNode* parseHex(const QoreProgramLocation* loc, const char* buf, int len);
580 DLLLOCAL void print_node(FILE* fp, const QoreValue qv);
581 DLLLOCAL void delete_global_variables();
582 DLLLOCAL void init_lib_intern(char* env[]);
583 DLLLOCAL QoreParseListNode* make_args(const QoreProgramLocation* loc, QoreValue arg);
584 
585 DLLLOCAL QoreValue copy_value_and_resolve_lvar_refs(const QoreValue& n, ExceptionSink* xsink);
586 
587 DLLLOCAL void init_qore_types();
588 DLLLOCAL void delete_qore_types();
589 
590 DLLLOCAL QoreListNode* stat_to_list(const struct stat& sbuf);
591 DLLLOCAL QoreHashNode* stat_to_hash(const struct stat& sbuf, const TypedHashDecl* hd = hashdeclStatInfo);
592 DLLLOCAL QoreHashNode* statvfs_to_hash(const struct statvfs& statvfs);
593 
594 // only called in stage 1 parsing: true means node requires run-time evaluation
595 //DLLLOCAL bool needsEval(AbstractQoreNode* n);
596 
597 DLLLOCAL const char* check_hash_key(const QoreHashNode* h, const char* key, const char* err, ExceptionSink* xsink);
598 
599 // class for master namespace of all builtin classes, constants, etc
600 class StaticSystemNamespace : public RootQoreNamespace {
601 public:
602  DLLLOCAL StaticSystemNamespace();
603 
604  DLLLOCAL ~StaticSystemNamespace();
605 };
606 
607 // master namespace of all builtin classes, constants, etc
608 DLLLOCAL extern StaticSystemNamespace* staticSystemNamespace;
609 
610 class QoreParseListNodeParseInitHelper {
611 private:
612  QoreParseListNode* l;
613  int pos = -1;
614  LocalVar* oflag;
615  int pflag;
616  int& lvids;
617 
618 public:
619  DLLLOCAL QoreParseListNodeParseInitHelper(QoreParseListNode* n_l, LocalVar* n_oflag, int n_pflag, int& n_lvids) :
620  l(n_l), oflag(n_oflag), pflag(n_pflag), lvids(n_lvids) {
621  }
622 
623  DLLLOCAL QoreValue parseInit(const QoreTypeInfo*& typeInfo) {
624  //printd(0, "QoreListNodeParseInitHelper::parseInit() this=%p %d/%d (l=%p)\n", this, index(), getList()->size(), getList());
625 
626  typeInfo = nullptr;
627  QoreValue& n = l->getReference(pos);
628  parse_init_value(n, oflag, pflag, lvids, typeInfo);
629  return n;
630  }
631 
632  DLLLOCAL bool next() {
633  ++pos;
634  if (pos == (int)l->size()) {
635  pos = -1;
636  return false;
637  }
638  return true;
639  }
640 
641  DLLLOCAL int index() {
642  return pos;
643  }
644 };
645 
646 class QorePossibleListNodeParseInitHelper {
647 private:
648  LocalVar* oflag;
649  int pflag;
650  int& lvids;
651  QoreListNode* l;
652  bool finished;
653  qore_size_t pos = -1;
654  const QoreTypeInfo* singleTypeInfo = nullptr;
655 
656 public:
657  DLLLOCAL QorePossibleListNodeParseInitHelper(QoreValue& n, LocalVar* n_oflag, int n_pflag, int& n_lvids) :
658  oflag(n_oflag),
659  pflag(n_pflag),
660  lvids(n_lvids),
661  l(n.getType() == NT_LIST ? n.get<QoreListNode>() : nullptr),
662  finished(!l) {
663  // if the expression is not a list, then initialize it now
664  // and save the return type
665  if (!l) {
666  parse_init_value(n, oflag, pflag, lvids, singleTypeInfo);
667  // set type info to 0 if the expression can return a list
668  // FIXME: set list element type here when list elements can have types
669  //printd(0, "singleTypeInfo=%s la=%d\n", QoreTypeInfo::getName(singleTypeInfo), QoreTypeInfo::parseAccepts(listTypeInfo, singleTypeInfo));
670  if (QoreTypeInfo::parseAccepts(listTypeInfo, singleTypeInfo))
671  singleTypeInfo = 0;
672  }
673  }
674 
675  DLLLOCAL bool noArgument() const {
676  return finished;
677  }
678 
679  DLLLOCAL bool next() {
680  ++pos;
681 
682  if (finished)
683  return false;
684 
685  if (pos == l->size()) {
686  finished = true;
687  return false;
688  }
689  return true;
690  }
691 
692  DLLLOCAL void parseInit(const QoreTypeInfo*& typeInfo);
693 };
694 
695 DLLLOCAL void raise_nonexistent_method_call_warning(const QoreProgramLocation* loc, const QoreClass* qc, const char* method);
696 
697 /*
698 class abstract_assignment_helper {
699 public:
700  DLLLOCAL virtual AbstractQoreNode* swapImpl(AbstractQoreNode* v, ExceptionSink* xsink) = 0;
701  DLLLOCAL virtual AbstractQoreNode* getValueImpl() const = 0;
702 };
703 */
704 
705 class qore_hash_private;
706 class qore_object_private;
707 class HashMember;
708 
709 class hash_assignment_priv {
710 public:
711  qore_hash_private& h;
712  HashMember* om;
713  qore_object_private* o = nullptr;
714 
715  DLLLOCAL hash_assignment_priv(qore_hash_private& n_h, HashMember* n_om) : h(n_h), om(n_om) {
716  }
717 
718  DLLLOCAL hash_assignment_priv(qore_hash_private& n_h, const char* key, bool must_already_exist = false, qore_object_private* obj = nullptr);
719 
720  DLLLOCAL hash_assignment_priv(QoreHashNode& n_h, const char* key, bool must_already_exist = false);
721 
722  DLLLOCAL hash_assignment_priv(QoreHashNode& n_h, const std::string &key, bool must_already_exist = false);
723 
724  DLLLOCAL hash_assignment_priv(ExceptionSink* xsink, QoreHashNode& n_h, const QoreString& key, bool must_already_exist = false);
725 
726  DLLLOCAL hash_assignment_priv(ExceptionSink* xsink, QoreHashNode& n_h, const QoreString* key, bool must_already_exist = false);
727 
728  DLLLOCAL void reassign(const char* key, bool must_already_exist = false);
729 
730  DLLLOCAL QoreValue swapImpl(QoreValue v);
731 
732  DLLLOCAL QoreValue getImpl() const;
733 
734  DLLLOCAL QoreValue operator*() const {
735  return getImpl();
736  }
737 
738  DLLLOCAL bool exists() const {
739  return (bool)om;
740  }
741 
742  DLLLOCAL void assign(QoreValue v, ExceptionSink* xsink);
743 
744  DLLLOCAL void assign(QoreValue v, SafeDerefHelper& sdh, ExceptionSink* xsink);
745 
746  DLLLOCAL QoreValue swap(QoreValue v) {
747  return swapImpl(v);
748  }
749 
750  DLLLOCAL static hash_assignment_priv* get(HashAssignmentHelper& h) {
751  return h.priv;
752  }
753 };
754 
755 DLLLOCAL void qore_machine_backtrace();
756 
757 #ifndef QORE_THREAD_STACK_BLOCK
758 #define QORE_THREAD_STACK_BLOCK 64
759 #endif
760 
761 template <typename T, int S1 = QORE_THREAD_STACK_BLOCK>
762 class ThreadBlock {
763 private:
764  DLLLOCAL ThreadBlock(const ThreadBlock&);
765 
766 public:
767  T var[S1];
768  int pos = 0;
769  ThreadBlock<T, S1>* prev, * next = nullptr;
770 
771  DLLLOCAL ThreadBlock(ThreadBlock* prev = nullptr) : prev(prev) { }
772  DLLLOCAL ~ThreadBlock() { }
773  DLLLOCAL T& get(int p) {
774  return var[p];
775  }
776 
777  DLLLOCAL bool frameBoundary(int p);
778 };
779 
780 template <typename T, int S1 = QORE_THREAD_STACK_BLOCK>
781 class ThreadLocalDataIterator {
782  typedef ThreadLocalDataIterator<T, S1> self_t;
783 
784 public:
785  typedef ThreadBlock<T, S1> Block;
786 
787 protected:
788  Block* orig = nullptr, * curr = nullptr;
789  int pos = 0;
790 
791 public:
792  DLLLOCAL ThreadLocalDataIterator(Block* n_orig)
793  : orig(n_orig && n_orig->pos ? n_orig : nullptr) {
794  }
795 
796  DLLLOCAL ThreadLocalDataIterator() {
797  }
798 
799  DLLLOCAL bool next() {
800  if (!orig) {
801  return false;
802  }
803 
804  do {
805  if (!curr) {
806  curr = orig;
807  pos = orig->pos - 1;
808  } else {
809  --pos;
810  if (pos < 0) {
811  if (!curr->prev) {
812  curr = 0;
813  pos = 0;
814  return false;
815  }
816  curr = curr->prev;
817  pos = curr->pos - 1;
818  }
819  }
820  //printd(5, "ThreadLocalDataIterator::next() this: %p curr: %p pos: %d b: %d\n", this, curr, pos, curr->frameBoundary(pos));
821  } while (curr->frameBoundary(pos));
822 
823  return true;
824  }
825 
826  DLLLOCAL T& get() {
827  assert(curr);
828  return curr->get(pos);
829  }
830 };
831 
832 template <typename T, int S1 = QORE_THREAD_STACK_BLOCK>
833 class ThreadLocalData {
834 public:
835  typedef ThreadBlock<T, S1> Block;
836  typedef ThreadLocalDataIterator<T, S1> iterator;
837 
838  Block* curr;
839 
840  DLLLOCAL ThreadLocalData() {
841  curr = new Block;
842  //printf("this=%p: first curr=%p\n", this, curr);
843  }
844 
845  DLLLOCAL ~ThreadLocalData() {
846 #ifdef DEBUG
847  //if (curr->pos)
848  //printf("~ThreadLocalData::~~ThreadLocalData() this=%p: del curr=%p pos=%d next=%p prev=%p\n", this, curr, curr->pos, curr->next, curr->prev);
849 #endif
850  assert(!curr->prev);
851  assert(!curr->pos);
852  if (curr->next)
853  delete curr->next;
854  delete curr;
855  }
856 #ifdef DEBUG
857  DLLLOCAL bool empty() const {
858  return (!curr->pos && !curr->prev);
859  }
860 #endif
861 
862  DLLLOCAL int getFrameCount() const {
863  return frame_count;
864  }
865 
866 protected:
867  int frame_count = -1;
868 
869 private:
870  DLLLOCAL ThreadLocalData(const ThreadLocalData&);
871 };
872 
873 // maps from Q_AF_* to standard system AF_ constants
874 DLLLOCAL int q_get_af(int type);
875 // maps from AF_* to Q_AF_ constants
876 DLLLOCAL int q_get_raf(int type);
877 // maps from Q_SOCK_ to standard system SOCK_ constants
878 DLLLOCAL int q_get_sock_type(int t);
879 
880 class OptHashRefHelper {
881  const ReferenceNode* ref;
882  ExceptionSink* xsink;
884 
885 public:
886  DLLLOCAL OptHashRefHelper(QoreListNode* args, unsigned i, ExceptionSink* n_xsink) : ref(test_reference_param(args, i)), xsink(n_xsink), info(ref ? new QoreHashNode(autoTypeInfo) : 0, xsink) {
887  }
888  DLLLOCAL OptHashRefHelper(const ReferenceNode* n_ref, ExceptionSink* n_xsink) : ref(n_ref), xsink(n_xsink), info(ref ? new QoreHashNode(autoTypeInfo) : 0, xsink) {
889  }
890  DLLLOCAL ~OptHashRefHelper() {
891  if (!ref)
892  return;
893 
894  ExceptionSink xs;
895  QoreTypeSafeReferenceHelper rh(ref, &xs);
896  if (xs)
897  xsink->assimilate(xs);
898  if (!rh)
899  return;
900 
901  rh.assign(info.release());
902  if (xs)
903  xsink->assimilate(xs);
904  }
905  DLLLOCAL QoreHashNode* operator*() {
906  return *info;
907  }
908 };
909 
910 // pushes a marker on the local variable parse stack so that searches can skip to global thread-local variables when the search hits the marker
911 class VariableBlockHelper {
912 public:
913  DLLLOCAL VariableBlockHelper();
914  DLLLOCAL ~VariableBlockHelper();
915 };
916 
917 class ParseOptionMaps {
918 protected:
919  DLLLOCAL void doMap(int64 code, const char* desc, const char* dom = nullptr);
920 
921 public:
922  typedef std::map<int64, const char*> pomap_t;
923  typedef std::map<const char*, int64, ltstr> pormap_t;
924 
925  pomap_t pomap, dommap;
926  pormap_t pormap, domrmap;
927 
928  DLLLOCAL ParseOptionMaps();
929 
930  DLLLOCAL QoreHashNode* getCodeToStringMap() const;
931  DLLLOCAL QoreHashNode* getStringToCodeMap() const;
932 
933  DLLLOCAL QoreHashNode* getDomainToStringMap() const;
934  DLLLOCAL QoreHashNode* getStringToDomainMap() const;
935 };
936 
937 DLLLOCAL extern ParseOptionMaps pomaps;
938 
939 DLLLOCAL extern QoreString YamlNullString;
940 
941 DLLLOCAL extern bool q_disable_gc;
942 
943 DLLLOCAL QoreValue qore_parse_get_define_value(const QoreProgramLocation* loc, const char* str, QoreString& arg, bool& ok);
944 
945 #ifndef HAVE_INET_NTOP
946 DLLLOCAL const char* inet_ntop(int af, const void* src, char* dst, size_t size);
947 #endif
948 #ifndef HAVE_INET_PTON
949 DLLLOCAL int inet_pton(int af, const char* src, void* dst);
950 #endif
951 
952 DLLLOCAL AbstractQoreNode* missing_function_error(const char* func, ExceptionSink* xsink);
953 DLLLOCAL AbstractQoreNode* missing_function_error(const char* func, const char* opt, ExceptionSink* xsink);
954 DLLLOCAL AbstractQoreNode* missing_method_error(const char* meth, const char* opt, ExceptionSink* xsink);
955 
956 // checks for illegal $self assignments in an object context
957 DLLLOCAL void check_self_assignment(const QoreProgramLocation* loc, QoreValue n, LocalVar* selfid);
958 
959 DLLLOCAL void ignore_return_value(QoreSimpleValue& n);
960 
961 DLLLOCAL void qore_string_init();
962 
963 DLLLOCAL QoreListNode* split_intern(const char* pattern, qore_size_t pl, const char* str, qore_size_t sl, const QoreEncoding* enc, bool with_separator = false);
964 DLLLOCAL QoreStringNode* join_intern(const QoreStringNode* p0, const QoreListNode* l, int offset, ExceptionSink* xsink);
965 DLLLOCAL QoreListNode* split_with_quote(ExceptionSink* xsink, const QoreString* sep, const QoreString* str,
966  const QoreString* quote, bool trim_unquoted, AbstractIteratorHelper* h = nullptr,
967  const QoreString* eol = nullptr);
968 DLLLOCAL bool inlist_intern(const QoreValue arg, const QoreListNode* l, ExceptionSink* xsink);
969 DLLLOCAL QoreStringNode* format_float_intern(const QoreString& fmt, double num, ExceptionSink* xsink);
970 DLLLOCAL QoreStringNode* format_float_intern(int prec, const QoreString& dsep, const QoreString& tsep, double num, ExceptionSink* xsink);
971 DLLLOCAL DateTimeNode* make_date_with_mask(const AbstractQoreZoneInfo* tz, const QoreString& dtstr, const QoreString& mask, ExceptionSink* xsink);
972 DLLLOCAL QoreHashNode* date_info(const DateTime& d);
973 DLLLOCAL void init_charmaps();
974 DLLLOCAL int do_unaccent(QoreString& str, const QoreString& src, ExceptionSink* xsink);
975 DLLLOCAL int do_unaccent(QoreString& str, const QoreString& src, ExceptionSink* xsink);
976 DLLLOCAL int do_tolower(QoreString& str, const QoreString& src, ExceptionSink* xsink);
977 DLLLOCAL int do_toupper(QoreString& str, const QoreString& src, ExceptionSink* xsink);
978 
979 DLLLOCAL int64 q_clock_getmillis();
980 DLLLOCAL int64 q_clock_getmicros();
981 DLLLOCAL int64 q_clock_getnanos();
982 
983 DLLLOCAL void qore_init_random_salt();
984 DLLLOCAL int qore_get_ptr_hash(QoreString& str, const void* ptr);
985 
986 // find the position of the first path separator in the string, or 0
987 DLLLOCAL const char* q_find_first_path_sep(const char* path);
988 // find the position of the last path separator in the string, or 0
989 DLLLOCAL const char* q_find_last_path_sep(const char* path);
990 
991 // reutrns the given file's mode or 0 if the stat() call fails
992 DLLLOCAL int q_get_mode(const QoreString& path);
994 
996 DLLLOCAL qore_offset_t q_UTF8_get_char_len(const char* p, qore_size_t valid_len);
997 
999 
1001 DLLLOCAL qore_offset_t q_UTF16BE_get_char_len(const char* p, qore_size_t valid_len);
1002 DLLLOCAL qore_offset_t q_UTF16LE_get_char_len(const char* p, qore_size_t len);
1003 
1004 DLLLOCAL int64 get_ms_zero(const QoreValue& v);
1005 
1006 DLLLOCAL AbstractQoreNode* copy_strip_complex_types(const AbstractQoreNode* n);
1007 DLLLOCAL QoreValue copy_strip_complex_types(const QoreValue& n);
1008 
1009 // for IPv4/v6 only
1010 DLLLOCAL void* qore_get_in_addr(struct sockaddr *sa);
1011 // for IPv4/v6 only
1012 DLLLOCAL size_t qore_get_in_len(struct sockaddr *sa);
1013 
1014 DLLLOCAL QoreHashNode* get_source_location(const QoreProgramLocation* loc);
1015 
1016 DLLLOCAL void qore_delete_module_options();
1017 
1018 DLLLOCAL const QoreTypeInfo* qore_get_type_from_string_intern(const char* str);
1019 
1020 DLLLOCAL QoreValue get_call_reference_intern(QoreObject* self, const QoreStringNode* identifier, ExceptionSink* xsink);
1021 
1022 #endif
qore_offset_t
intptr_t qore_offset_t
used for offsets that could be negative
Definition: common.h:76
QoreProgram
supports parsing and executing Qore-language code, reference counted, dynamically-allocated only
Definition: QoreProgram.h:126
QoreListNode::size
DLLEXPORT size_t size() const
returns the number of elements in the list
QoreValue
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:262
test_reference_param
static const ReferenceNode * test_reference_param(const QoreListNode *n, qore_size_t i)
returns a ReferenceNode pointer for the argument position given or 0 if there is no argument there or...
Definition: params.h:65
SafeDerefHelper
Helps dereference values outside of locks.
Definition: QoreLibIntern.h:462
QoreHashNode
This is the hash or associative list container type in Qore, dynamically allocated only,...
Definition: QoreHashNode.h:50
ReferenceHolder::release
DLLLOCAL T * release()
releases the pointer to the caller
Definition: ReferenceHolder.h:83
ReferenceHolder< QoreHashNode >
QoreClass
defines a Qore-language class
Definition: QoreClass.h:239
qore_size_t
size_t qore_size_t
used for sizes (same range as a pointer)
Definition: common.h:73
QoreListNode
This is the list container type in Qore, dynamically allocated only, reference counted.
Definition: QoreListNode.h:52
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
arg_vec_t
std::vector< QoreValue > arg_vec_t
vector of value information for default argument lists
Definition: common.h:254
SafeDerefHelper::~SafeDerefHelper
DLLLOCAL ~SafeDerefHelper()
must be destroyed outside of any locks
Definition: QoreLibIntern.h:468
parseHex
DLLEXPORT BinaryNode * parseHex(const char *buf, int len, ExceptionSink *xsink)
parses a string of hex characters and returns a BinaryNode
QoreTypeSafeReferenceHelper
helper class to manage variable references passed to functions and class methods, stack only,...
Definition: QoreTypeSafeReferenceHelper.h:57
QoreString
Qore's string type supported by the QoreEncoding class.
Definition: QoreString.h:81
DateTimeNode
Qore's parse tree/value type for date-time values, reference-counted, dynamically-allocated only.
Definition: DateTimeNode.h:45
SafeDerefHelper::add
DLLLOCAL void add(QoreValue v)
adds a value for dereferencing on exit
Definition: QoreLibIntern.h:487
qore_license_t
qore_license_t
qore library and module license type identifiers
Definition: common.h:85
QoreValue::discard
DLLEXPORT void discard(ExceptionSink *xsink)
dereferences any contained AbstractQoreNode pointer and sets to 0; does not modify other values
TypedHashDecl
typed hash declaration
Definition: TypedHashDecl.h:44
QoreValue::derefCanThrowException
DLLEXPORT bool derefCanThrowException() const
returns true if a dereference could theoretically throw an exception (an object is reachable from thi...
ExceptionSink::assimilate
DLLEXPORT void assimilate(ExceptionSink *xs)
assimilates all entries of the "xs" argument by appending them to the internal list and deletes the "...
ReferenceNode
parse type: reference to a lvalue expression
Definition: ReferenceNode.h:45
QoreObject
the implementation of Qore's object data type, reference counted, dynamically-allocated only
Definition: QoreObject.h:61
ExceptionSink
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:48
SafeDerefHelper::deref
DLLLOCAL void deref(QoreValue v)
dereferences the value immediately if it cannot throw an exception, or adds it to the list for derefe...
Definition: QoreLibIntern.h:478
HashAssignmentHelper
use this class to make assignments to hash keys from a pointer to the key value
Definition: QoreHashNode.h:671
QoreThreadLock
provides a mutually-exclusive thread lock
Definition: QoreThreadLock.h:49
DateTime
Holds absolute and relative date/time values in Qore with precision to the microsecond.
Definition: DateTime.h:93
NT_LIST
const qore_type_t NT_LIST
type value for QoreListNode
Definition: node_types.h:50
num_params
static unsigned num_params(const QoreListNode *n)
returns the number of arguments passed to the function
Definition: params.h:54
type_vec_t
std::vector< const QoreTypeInfo * > type_vec_t
vector of type information for parameter lists
Definition: common.h:251
QoreEncoding
defines string encoding functions in Qore
Definition: QoreEncoding.h:83
BinaryNode
holds arbitrary binary data
Definition: BinaryNode.h:41
name_vec_t
std::vector< std::string > name_vec_t
vector of parameter names for parameter lists
Definition: common.h:257
RootQoreNamespace
the root namespace of a QoreProgram object
Definition: QoreNamespace.h:335
QoreStringNode
Qore's string value type, reference counted, dynamically-allocated only.
Definition: QoreStringNode.h:50
AbstractQoreNode
The base class for all value and parse types in Qore expression trees.
Definition: AbstractQoreNode.h:54
qore_type_t
int16_t qore_type_t
used to identify unique Qore data and parse types (descendents of AbstractQoreNode)
Definition: common.h:70
HashAssignmentHelper::priv
class hash_assignment_priv * priv
private implementation
Definition: QoreHashNode.h:764