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