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