32#ifndef _QORE_QORE_PROGRAM_PRIVATE_H
33#define _QORE_QORE_PROGRAM_PRIVATE_H
40#include "qore/intern/ParserSupport.h"
41#include "qore/intern/QoreNamespaceIntern.h"
42#include "qore/intern/QC_AutoReadLock.h"
43#include "qore/intern/QC_AutoWriteLock.h"
44#include "qore/intern/QC_Program.h"
45#include "qore/intern/QC_ProgramControl.h"
46#include "qore/intern/ReturnStatement.h"
47#include "qore/intern/StreamReader.h"
48#include "qore/intern/StreamWriter.h"
50#include "qore/QoreDebugProgram.h"
51#include "qore/QoreRWLock.h"
52#include "qore/vector_map"
53#include "qore/vector_set"
60typedef vector_map_t<int, unsigned> ptid_map_t;
63typedef std::vector<AbstractStatement*> stmt_vec_t;
65class QoreParseLocationHelper {
67 DLLLOCAL QoreParseLocationHelper(
const char* file,
const char* src =
nullptr,
int offset = 0) {
69 thread_set_class_and_ns(
nullptr,
nullptr, cls, ns);
70 beginParsing(file,
nullptr, src, offset);
73 DLLLOCAL ~QoreParseLocationHelper() {
75 thread_set_class_and_ns(cls, ns);
80 const qore_class_private* cls;
85typedef safe_dslist<LocalVar*> local_var_list_t;
88typedef StatementBlock* q_exp_t;
90class LocalVariableList :
public local_var_list_t {
92 DLLLOCAL LocalVariableList() {
95 DLLLOCAL ~LocalVariableList() {
96 for (local_var_list_t::iterator i = begin(), e = end(); i != e; ++i) {
104#include "qore/intern/ThreadLocalVariableData.h"
105#include "qore/intern/ThreadClosureVariableStack.h"
107hashdecl ThreadLocalProgramData {
110 ThreadLocalVariableData lvstack;
112 ThreadClosureVariableStack cvstack;
114 const AbstractQoreZoneInfo* tz =
nullptr;
121 DLLLOCAL ThreadLocalProgramData() : tz_set(false), inst(false) {
122 printd(5,
"ThreadLocalProgramData::ThreadLocalProgramData() this: %p\n",
this);
125 DLLLOCAL ~ThreadLocalProgramData() {
126 printd(5,
"ThreadLocalProgramData::~ThreadLocalProgramData() this: %p, rs: %d\n",
this, runState);
127 assert(lvstack.empty());
128 assert(cvstack.empty());
132 lvstack.finalize(sdh);
133 cvstack.finalize(sdh);
142 DLLLOCAL
void setTZ(
const AbstractQoreZoneInfo* n_tz) {
147 DLLLOCAL
void clearTZ() {
185 DLLLOCAL
int dbgStep(
const StatementBlock* blockStatement,
const AbstractStatement* statement,
ExceptionSink* xsink);
189 DLLLOCAL
void dbgFunctionEnter(
const StatementBlock* statement,
ExceptionSink* xsink);
193 DLLLOCAL
void dbgFunctionExit(
const StatementBlock* statement,
QoreValue& returnValue,
ExceptionSink* xsink);
197 DLLLOCAL
void dbgException(
const AbstractStatement* statement,
ExceptionSink* xsink);
206 DLLLOCAL
void dbgBreak() {
207 printd(5,
"ThreadLocalProgramData::dbgBreak(), this: %p\n",
this);
213 DLLLOCAL
void dbgPendingAttach() {
214 printd(5,
"ThreadLocalProgramData::dbgPendingAttach(), this: %p\n",
this);
220 DLLLOCAL
void dbgPendingDetach() {
221 printd(5,
"ThreadLocalProgramData::dbgPendingDetach(), this: %p\n",
this);
228 DLLLOCAL
bool dbgIsAttached() {
229 return runState != DBG_RS_DETACH;
234 DLLLOCAL ThreadLocalProgramData(
const ThreadLocalProgramData& old) =
delete;
237 DebugRunStateEnum runState = DBG_RS_DETACH;
239 const AbstractStatement* runToStatement =
nullptr;
241 int functionCallLevel = 0;
243 DLLLOCAL
inline void setRunState(DebugRunStateEnum rs,
const AbstractStatement* rts) {
244 assert(rs < DBG_RS_STOPPED);
245 if (rs == DBG_RS_UNTIL_RETURN) {
246 functionCallLevel = 1;
248 printd(5,
"ThreadLocalProgramData::setRunState(), this: %p, rs: %d->%d, rts: %p\n",
this, runState, rs, rts);
250 runToStatement = rts;
253 volatile bool breakFlag =
false;
255 DLLLOCAL
inline void checkBreakFlag() {
256 if (breakFlag && runState != DBG_RS_DETACH) {
258 if (runState != DBG_RS_STOPPED) {
259 runState = DBG_RS_STEP;
261 printd(5,
"ThreadLocalProgramData::checkBreakFlag(), this: %p, rs: %d\n",
this, runState);
267 if (runState != DBG_RS_STOPPED) {
268 if (attachFlag > 0) {
273 }
else if (attachFlag < 0) {
282typedef vector_map_t<ThreadProgramData*, ThreadLocalProgramData*> pgm_data_map_t;
286typedef vector_map_t<std::string, QoreValue> dmap_t;
290typedef vector_map_t<const char*, int64> ppo_t;
293class AbstractQoreZoneInfo;
297 DLLLOCAL
bool operator()(
const QoreProgramLocation* p1,
const QoreProgramLocation* p2)
const {
305hashdecl pgmloc_vec_t :
public std::vector<QoreProgramLocation*> {
306 DLLLOCAL ~pgmloc_vec_t() {
310 DLLLOCAL
void clear() {
311 for (
auto& i : *
this) {
315 std::vector<QoreProgramLocation*>::clear();
319class qore_program_private_base {
320 friend class QoreProgramAccessHelper;
323 LocalVariableList local_var_list;
328 unsigned thread_count = 0;
329 unsigned thread_waiting = 0;
330 unsigned parse_count = 0;
340 typedef std::set<const char*, ltstr> str_set_t;
344 typedef std::set<const QoreProgramLocation*, ltpgm> loc_set_t;
347 typedef std::set<std::string> strset_t;
349 strset_t featureList;
352 strset_t userFeatureList;
355 strset_t parse_modules;
366 * warnSink =
nullptr,
367 * pendingParseSink =
nullptr;
372 TopLevelStatementBlock sb;
375 bool only_first_except : 1,
377 po_allow_restrict : 1,
380 requires_exception : 1,
382 parsing_in_progress : 1,
388 typedef std::set<q_exp_t> q_exp_set_t;
390 q_exp_t new_expression =
nullptr;
394 int exceptions_raised = 0,
397 ParseWarnOptions pwo;
402 std::string exec_class_name, script_dir, script_path, script_name, include_path;
409 mutable unsigned twaiting = 0;
412 pgm_data_map_t pgm_data_map;
415 const AbstractQoreZoneInfo* TZ;
433 : plock(&ma_recursive),
435 only_first_except(false),
437 po_allow_restrict(true),
440 requires_exception(false),
442 parsing_in_progress(false),
445 expression_mode(false),
446 pwo(n_parse_options),
448 printd(QPP_DBG_LVL,
"qore_program_private_base::qore_program_private_base() this: %p pgm: %p po: " QLLD
"\n",
449 this, pgm, n_parse_options);
452 pgm->priv = (qore_program_private*)
this;
455 setParent(p_pgm, n_parse_options);
457 TZ = QTZM.getLocalZoneInfo();
462 Var *var = qore_root_ns_private::runtimeCreateVar(*RootNS, *QoreNS,
"ARGV", listTypeInfo,
true);
464 var->setInitial(ARGV->
copy());
466 var = qore_root_ns_private::runtimeCreateVar(*RootNS, *QoreNS,
"QORE_ARGV", listTypeInfo,
true);
467 if (var && QORE_ARGV)
468 var->setInitial(QORE_ARGV->
copy());
470 var = qore_root_ns_private::runtimeCreateVar(*RootNS, *QoreNS,
"ENV", hashTypeInfo,
true);
472 var->setInitial(ENV->
copy());
477 DLLLOCAL ~qore_program_private_base() {
478 printd(QPP_DBG_LVL,
"qore_program_private_base::~qore_program_private_base() this: %p pgm: %p\n",
this, pgm);
482 DLLLOCAL
const QoreProgramLocation* getLocation(
int sline,
int eline);
483 DLLLOCAL
const QoreProgramLocation* getLocation(
const QoreProgramLocation&,
int sline,
int eline);
488 DLLLOCAL
int64 checkDeserializeParseOptions(
int64 po) {
492 return pwo.parse_options & ~po & ~PO_FREE_STYLE_OPTIONS;
495 DLLLOCAL
void replaceParseOptionsIntern(
int64 po) {
496 pwo.parse_options = po;
499 DLLLOCAL
bool checkSetParseOptions(
int64 po) {
505 DLLLOCAL
void setParseOptionsIntern(
int64 po) {
506 pwo.parse_options |= po;
509 DLLLOCAL
void addParseModule(
const char* mod) {
510 parse_modules.insert(mod);
514 typedef vector_map_t<const char*, AbstractQoreProgramExternalData*> extmap_t;
521 DLLLOCAL
void newProgram();
523 DLLLOCAL
void setDefines();
526class PreParseHelper {
528 qore_program_private_base *p;
532 DLLLOCAL PreParseHelper(qore_program_private_base *n_p) : p(n_p), swapped(false) {
534 if (!p->pendingParseSink)
536 p->parseSink = p->pendingParseSink;
541 DLLLOCAL ~PreParseHelper() {
543 p->parseSink =
nullptr;
548class qore_debug_program_private;
550class AutoQoreCounterDec {
552 DLLLOCAL AutoQoreCounterDec(
QoreCounter* n_cnt,
bool incNow =
true): cnt(n_cnt), incFlag(false) {
558 DLLLOCAL ~AutoQoreCounterDec() {
564 DLLLOCAL
void inc() {
573 DLLLOCAL AutoQoreCounterDec() {}
578class qore_program_private :
public qore_program_private_base {
580 typedef std::map<const char*, int, ltstr> section_offset_map_t;
582 typedef std::map<int, AbstractStatement*> sline_statement_map_t;
584 hashdecl section_sline_statement_map {
585 section_offset_map_t sectionMap;
586 sline_statement_map_t statementMap;
589 typedef section_sline_statement_map section_sline_statement_map_t;
591 typedef vector_map_t<const char*, section_sline_statement_map_t*> name_section_sline_statement_map_t;
596 DLLLOCAL ~qore_program_private();
598 DLLLOCAL
void registerProgram();
600 DLLLOCAL
void depRef() {
601 printd(QPP_DBG_LVL,
"qore_program_private::depRef() this: %p pgm: %p %d->%d\n",
this, pgm,
606 DLLLOCAL
void depDeref() {
607 printd(QPP_DBG_LVL,
"qore_program_private::depDeref() this: %p pgm: %p %d->%d\n",
this, pgm,
625 for (
auto& i : pgm_data_map) {
626 i.second->finalize(sdh);
632 for (
auto& i : pgm_data_map) {
633 i.second->del(xsink);
634 i.first->delProgram(pgm);
638 DLLLOCAL
void waitForTerminationAndClear(
ExceptionSink* xsink);
650 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed has already been deleted and therefore no "
651 "new threads can be started in it");
660 DLLLOCAL
void cancelPreregistration() {
664 assert(thread_count > 0);
665 if (!--thread_count && thread_waiting)
670 DLLLOCAL
void registerNewThread(
int tid) {
674 assert(thread_count);
696 if (ptid && ptid != tid) {
697 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed has already been deleted and therefore "
698 "cannot be accessed at runtime");
701 if (parsing_in_progress) {
702 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed is currently undergoing parsing and cannot "
703 "be accessed at runtime");
712 DLLLOCAL
void incThreadCount() {
718 if (ptid && ptid != tid) {
720 "therefore cannot be accessed at runtime");
722 if (parsing_in_progress) {
723 throw QoreStandardException(
"PROGRAM-ERROR",
"the Program accessed is currently undergoing parsing and "
724 "cannot be accessed at runtime");
731 DLLLOCAL
void decThreadCount(
int tid) {
735 ptid_map_t::iterator i = tidmap.find(tid);
736 assert(i != tidmap.end());
740 assert(thread_count > 0);
741 if (!--thread_count && thread_waiting)
750 for (
auto& i : tidmap) {
751 l.
push(i.first,
nullptr);
760 while (parse_tid != -1 && parse_tid != tid && !ptid) {
768 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed has already been deleted and "
769 "therefore cannot be accessed");
781 DLLLOCAL
void unlockParsing() {
785 assert(parse_count > 0);
786 if (!(--parse_count)) {
788 if (thread_waiting) {
794 DLLLOCAL
bool parsingLocked()
const {
799 DLLLOCAL
void waitForAllThreadsToTerminateIntern() {
802 ptid_map_t::iterator i = tidmap.find(tid);
803 unsigned adj = (i != tidmap.end() ? 1 : 0);
805 while ((thread_count - adj) || parse_count) {
812 DLLLOCAL
void waitForAllThreadsToTerminate() {
815 waitForAllThreadsToTerminateIntern();
818 DLLLOCAL
const char* parseGetScriptPath()
const {
819 return script_path.empty() ? nullptr : script_path.c_str();
822 DLLLOCAL
const char* parseGetScriptDir()
const {
823 return script_dir.empty() ? nullptr : script_dir.c_str();
826 DLLLOCAL
const char* parseGetScriptName()
const {
827 return script_name.empty() ? nullptr : script_name.c_str();
833 return script_path.empty() ? nullptr :
new QoreStringNode(script_path);
839 return script_dir.empty() ? nullptr :
new QoreStringNode(script_dir);
845 return script_name.empty() ? nullptr :
new QoreStringNode(script_name);
848 DLLLOCAL
void setScriptPathExtern(
const char* path) {
854 DLLLOCAL
void setScriptPath(
const char* path) {
864 script_dir =
"." QORE_DIR_SEP_STR;
865 script_path = script_dir + script_name;
869 script_dir.assign(path, p - path);
883 for (
auto& i : featureList) {
892 DLLLOCAL
int internParsePending(
ExceptionSink* xsink,
const char* code,
const char* label,
893 const char* orig_src =
nullptr,
int offset = 0,
bool standard_parse =
true) {
897 assert(code && code[0]);
901 const char* sname = label;
902 const char* src = orig_src;
904 addFile(src, sname, offset);
912 QoreParseLocationHelper qplh(sname, src, offset);
915 beginParsing(sname,
nullptr, src, offset);
917 if (!parsing_in_progress) {
918 parsing_in_progress =
true;
927 yy_scan_string(code, lexer);
928 yyset_lineno(1, lexer);
932 printd(5,
"qore_program_private::internParsePending() returned from yyparse()\n");
936 if (standard_parse) {
937 printd(5,
"qore_program_private::internParsePending() parse exception: calling parseRollback()\n");
938 internParseRollback(xsink);
939 requires_exception =
false;
943 printd(5,
"qore_program_private::internParsePending() about to call yylex_destroy()\n");
944 yylex_destroy(lexer);
945 printd(5,
"qore_program_private::internParsePending() returned from yylex_destroy()\n");
954 if (pendingParseSink) {
956 pendingParseSink =
nullptr;
962 xsink->
raiseException(
"PARSE-ERROR",
"parsing can only happen once for each Program container");
969 const char* orig_src =
nullptr,
int offset = 0) {
972 ProgramRuntimeParseContextHelper pch(xsink, pgm);
978 if (checkParse(xsink)) {
982 startParsing(xsink, wS, wm);
984 int rc = internParsePending(xsink, code, label, orig_src, offset);
993 DLLLOCAL
int internParseCommit(
bool standard_parse =
true);
996 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1002 if (checkParse(xsink)) {
1006 startParsing(xsink, wS, wm);
1009 int rc = internParseCommit();
1012 parseSink =
nullptr;
1020 ProgramRuntimeParseContextHelper pch(xsink, pgm);
1026 internParseRollback(xsink);
1032 printd(5,
"QoreProgram::parse(fp: %p, name: %s, xsink: %p, wS: %p, wm: %d)\n", fp, name, xsink, wS, wm);
1038 printd(5,
"QoreProgram::parse(fp: %p, name: %s) EOF\n", fp, name);
1047 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1052 if (checkParse(xsink)) {
1056 startParsing(xsink, wS, wm);
1060 const char* sname = name;
1066 QoreParseLocationHelper qplh(sname);
1069 beginParsing(sname);
1071 if (!parsing_in_progress) {
1072 parsing_in_progress =
true;
1077 yyset_in(fp, lexer);
1082 internParseCommit();
1085 parseSink =
nullptr;
1091 yylex_destroy(lexer);
1092 if (only_first_except && exceptions_raised > 1)
1093 fprintf(stderr,
"\n%d exception(s) skipped\n\n", exceptions_raised);
1097 int wm,
const QoreString* source =
nullptr,
int offset = 0) {
1113 if (source && !source->empty() && !src.
set(source,
QCS_DEFAULT, xsink))
1116 parse(tstr->c_str(), tlstr->c_str(), xsink, wS, wm, source ? src->
c_str() :
nullptr, offset);
1120 const char* orig_src =
nullptr,
int offset = 0) {
1123 assert(code && code[0]);
1126 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1131 if (checkParse(xsink)) {
1135 startParsing(xsink, wS, wm);
1138 if (!internParsePending(xsink, code, label, orig_src, offset))
1139 internParseCommit();
1142 parseSink =
nullptr;
1154 xsink->
raiseException(
"STATEMENT-ERROR",
"the statement cannot be empty");
1171 if (source && !source->empty() && !src.
set(source,
QCS_DEFAULT, xsink)) {
1175 return parseStatement(tstr->c_str(), tlstr->c_str(), xsink, wS, wm, source ? src->
c_str() :
nullptr, offset);
1179 int wm,
const char* orig_src =
nullptr,
int offset = 0) {
1182 assert(code && code[0]);
1185 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1190 startParsing(xsink, wS, wm);
1193 if (!internParsePending(xsink, code, label, orig_src, offset,
false)) {
1194 internParseCommit(
false);
1196 parsing_in_progress =
false;
1200 parseSink =
nullptr;
1203 return *xsink ? -1 : 0;
1211 xsink->
raiseException(
"EXPRESSION-ERROR",
"the expression cannot be empty");
1226 if (source && !source->empty() && !src.
set(source,
QCS_DEFAULT, xsink))
1229 return parseExpression(tstr->c_str(), tlstr->c_str(), xsink, wS, wm, source ? src->
c_str() :
nullptr, offset);
1233 int wm,
const char* orig_src =
nullptr,
int offset = 0) {
1236 assert(code && code[0]);
1239 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1244 assert(!expression_mode);
1245 assert(!new_expression);
1246 expression_mode =
true;
1248 QoreStringMaker exp_code(
"return (%s);", code);
1250 startParsing(xsink, wS, wm);
1253 if (!internParsePending(xsink, exp_code.c_str(), label, orig_src, offset,
false)) {
1254 internParseCommit(
false);
1256 parsing_in_progress =
false;
1260 parseSink =
nullptr;
1264 expression_mode =
false;
1265 q_exp_t rv = new_expression;
1266 if (new_expression) {
1268 exp_set.erase(new_expression);
1269 delete new_expression;
1272 new_expression =
nullptr;
1278 QORE_TRACE(
"QoreProgram::parseFile()");
1280 printd(5,
"QoreProgram::parseFile(%s)\n", filename);
1283 if (!(fp = fopen(filename,
"r"))) {
1284 if ((only_first_except && !exceptions_raised) || !only_first_except)
1285 xsink->
raiseErrnoException(
"PARSE-EXCEPTION", errno,
"cannot open qore script '%s'", filename);
1286 exceptions_raised++;
1289 ON_BLOCK_EXIT(fclose, fp);
1291 setScriptPath(filename);
1293 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1297 parse(fp, filename, xsink, wS, wm);
1301 assert(!str->
empty());
1315 if (source && !source->empty() && !src.
set(source,
QCS_DEFAULT, xsink))
1318 parsePending(tstr->c_str(), tlstr->c_str(), xsink, wS, wm, source ? src->
c_str() :
nullptr, offset);
1322 DLLLOCAL
void importFunction(
ExceptionSink* xsink, QoreFunction *u,
const qore_ns_private& oldns,
const char* new_name =
nullptr,
bool inject =
false);
1330 thread_local_storage->
set(h);
1338 printd(5,
"QoreProgram::clearThreadData() this: %p h: %p (size: %d)\n",
this, h, h ? h->
size() : 0);
1348 thread_local_storage->
set(
nullptr);
1352 DLLLOCAL
void finalizeThreadData(ThreadProgramData* td,
SafeDerefHelper& sdh) {
1356 thread_local_storage->
set(
nullptr);
1364 pgm_data_map_t::iterator i = pgm_data_map.find(td);
1365 if (i != pgm_data_map.end()) {
1366 i->second->finalize(sdh);
1371 DLLLOCAL
int endThread(ThreadProgramData* td,
ExceptionSink* xsink) {
1372 ThreadLocalProgramData* tlpd =
nullptr;
1381 pgm_data_map_t::iterator i = pgm_data_map.find(td);
1382 if (i == pgm_data_map.end()) {
1386 pgm_data_map.erase(i);
1393 DLLLOCAL
void doTopLevelInstantiation(ThreadLocalProgramData& tlpd) {
1395 const LVList* lvl = sb.getLVList();
1397 for (
unsigned i = 0; i < lvl->size(); ++i) {
1398 lvl->lv[i]->instantiate();
1408 DLLLOCAL
bool setThreadVarData(ThreadProgramData* td, ThreadLocalProgramData*& new_tlpd,
bool run) {
1422 pgm_data_map_t::iterator i = pgm_data_map.find(td);
1423 if (i == pgm_data_map.end()) {
1426 ThreadLocalProgramData* tlpd =
new ThreadLocalProgramData;
1428 printd(5,
"qore_program_private::setThreadVarData() (first) this: %p pgm: %p td: %p run: %s inst: %s\n",
this, pgm, td, run ?
"true" :
"false", tlpd->inst ?
"true" :
"false");
1432 pgm_data_map.insert(pgm_data_map_t::value_type(td, tlpd));
1437 printd(5,
"qore_program_private::setThreadVarData() (first) this: %p pgm: %p td: %p\n",
this, pgm, td);
1438 doTopLevelInstantiation(*tlpd);
1444 ThreadLocalProgramData* tlpd = pgm_data_map[td];
1449 printd(5,
"qore_program_private::setThreadVarData() (not first) this: %p pgm: %p td: %p run: %s inst: %s\n",
this, pgm, td, run ?
"true" :
"false", tlpd->inst ?
"true" :
"false");
1451 if (run && !tlpd->inst) {
1452 doTopLevelInstantiation(*tlpd);
1458 DLLLOCAL
const AbstractQoreZoneInfo*
currentTZ(ThreadProgramData* tpd = get_thread_program_data())
const {
1460 pgm_data_map_t::const_iterator i = pgm_data_map.find(tpd);
1461 if (i != pgm_data_map.end() && i->second->tz_set)
1462 return i->second->tz;
1466 DLLLOCAL
void setTZ(
const AbstractQoreZoneInfo* n_TZ) {
1470 DLLLOCAL
void exportFunction(
ExceptionSink* xsink, qore_program_private* p,
const char* name,
const char* new_name =
nullptr,
bool inject =
false) {
1472 xsink->
raiseException(
"FUNCTION-IMPORT-ERROR",
"cannot import a function from the same Program object");
1477 xsink->
raiseException(
"FUNCTION-IMPORT-ERROR",
"cannot import function \"%s\" in a Program object without PO_ALLOW_INJECTION set", name);
1481 const QoreFunction* u;
1482 const qore_ns_private* ns =
nullptr;
1485 ProgramRuntimeParseAccessHelper rah(xsink, pgm);
1488 u = qore_root_ns_private::runtimeFindFunction(*RootNS, name, ns);
1492 xsink->
raiseException(
"PROGRAM-IMPORTFUNCTION-NO-FUNCTION",
"function '%s' does not exist in the current program scope", name);
1495 p->importFunction(xsink,
const_cast<QoreFunction*
>(u), *ns, new_name, inject);
1499 DLLLOCAL
bool parseExceptionRaised()
const {
1504 DLLLOCAL
void disableParseOptionsIntern(
int64 po) {
1505 pwo.parse_options &= ~po;
1510 if (checkSetParseOptions(po)) {
1511 xsink->
raiseException(
"OPTIONS-LOCKED",
"parse options have been locked on this program object");
1515 setParseOptionsIntern(po);
1523 if (((po &
PO_FREE_OPTIONS) != po) && po_locked && !po_allow_restrict) {
1524 xsink->
raiseException(
"OPTIONS-LOCKED",
"parse options have been locked on this program object");
1528 disableParseOptionsIntern(po);
1535 xsink->
raiseException(
"OPTION-ERROR",
"the calling Program does not have the PO_NO_CHILD_PO_RESTRICTIONS option set, and therefore cannot call Program::replaceParseOptions()");
1540 replaceParseOptionsIntern(po);
1544 DLLLOCAL
int parseSetParseOptions(
const QoreProgramLocation* loc,
int64 po) {
1548 parse_error(*loc,
"parse options have been locked on this program object");
1552 setParseOptionsIntern(po);
1556 DLLLOCAL
int parseDisableParseOptions(
const QoreProgramLocation* loc,
int64 po) {
1559 if (((po &
PO_FREE_OPTIONS) != po) && po_locked && !po_allow_restrict) {
1560 parse_error(*loc,
"parse options have been locked on this program object");
1564 disableParseOptionsIntern(po);
1568 DLLLOCAL
void parseSetTimeZone(
const char* zone) {
1572 mergeParseException(xsink);
1576 const AbstractQoreZoneInfo *tz = (*zone ==
'-' || *zone ==
'+') ? QTZM.findCreateOffsetZone(zone, &xsink) : QTZM.findLoadRegion(zone, &xsink);
1579 mergeParseException(xsink);
1583 assert(tz || ((*zone ==
'-' || *zone ==
'+')));
1588 DLLLOCAL
void makeParseException(
const QoreProgramLocation& loc,
const char* err,
QoreStringNode* desc) {
1589 QORE_TRACE(
"QoreProgram::makeParseException()");
1592 if (!requires_exception) {
1593 if ((only_first_except && !exceptions_raised) || !only_first_except) {
1594 QoreException *ne =
new ParseException(loc, err, d.release());
1597 exceptions_raised++;
1601 DLLLOCAL
void parseException(
const QoreProgramLocation& loc,
const char* fmt, ...) {
1605 if (requires_exception)
1611 va_start(args, fmt);
1612 int rc = desc->
vsprintf(fmt, args);
1617 makeParseException(loc,
"PARSE-EXCEPTION", desc);
1623 dmap_t::iterator i = dmap.find(name);
1624 if (i != dmap.end()) {
1625 i->second.discard(xsink);
1635 DLLLOCAL
const QoreValue getDefine(
const char* name,
bool& is_defined) {
1636 dmap_t::iterator i = dmap.find(name);
1637 if (i != dmap.end()) {
1645 DLLLOCAL
QoreValue runTimeGetDefine(
const char* name,
bool& is_defined) {
1647 return getDefine(name, is_defined).refSelf();
1654 DLLLOCAL
bool unDefine(
const char* name,
ExceptionSink* xsink) {
1655 dmap_t::iterator i = dmap.find(name);
1656 if (i != dmap.end()) {
1657 i->second.discard(xsink);
1664 DLLLOCAL
bool parseUnDefine(
const char* name) {
1665 PreParseHelper pph(
this);
1666 return unDefine(name, parseSink);
1669 DLLLOCAL
bool runTimeUnDefine(
const char* name,
ExceptionSink* xsink) {
1671 return unDefine(name, xsink);
1675 DLLLOCAL
bool isDefined(
const char* name) {
1676 dmap_t::iterator i = dmap.find(name);
1677 return i == dmap.end() ? false :
true;
1680 DLLLOCAL
bool runTimeIsDefined(
const char* name) {
1682 return isDefined(name);
1685 DLLLOCAL
int checkDefine(
const QoreProgramLocation* loc,
const char* str,
ExceptionSink* xsink) {
1686 const char* p = str;
1688 xsink->
raiseException(*loc,
"PARSE-EXCEPTION", 0,
"illegal define variable '%s'; does not begin with an alphabetic character", p);
1693 if (!isalnum(*p) && *p !=
'_') {
1695 xsink->
raiseException(*loc,
"PARSE-EXCEPTION", 0,
"illegal character '%c' in define variable '%s'", *p, str);
1703 DLLLOCAL
void parseDefine(
const QoreProgramLocation* loc,
const char* str,
QoreValue val) {
1704 PreParseHelper pph(
this);
1706 if (checkDefine(loc, str, parseSink))
1709 setDefine(str, val, parseSink);
1713 const QoreProgramLocation* loc = get_runtime_location();
1715 if (checkDefine(loc, str, xsink))
1719 setDefine(str, val, xsink);
1724 ProgramRuntimeParseAccessHelper pah(xsink, pgm);
1727 return qore_root_ns_private::runtimeGetCallReference(*RootNS, name, xsink);
1730 DLLLOCAL
void pushParseOptions(
const char* pf) {
1732 ppo_t::iterator i = ppo.lower_bound(pf);
1733 if (i != ppo.end() && !strcmp(pf, i->first))
1735 ppo.insert(i, ppo_t::value_type(pf, pwo.parse_options));
1739 DLLLOCAL
void restoreParseOptions(
const char* pf) {
1740 ppo_t::iterator i = ppo.find(pf);
1741 if (i != ppo.end()) {
1743 pwo.parse_options = i->second;
1748 DLLLOCAL
void addParseException(
ExceptionSink& xsink,
const QoreProgramLocation* loc) {
1749 if (requires_exception) {
1756 xsink.overrideLocation(*loc);
1772 if ((pos & p_tmp) != pos) {
1773 rv = ((pos & p_tmp) ^ pos);
1777 int64 neg = (n_dom & ~PO_POSITIVE_OPTIONS);
1778 if (neg && (neg & pwo.parse_options)) {
1779 rv |= (neg & pwo.parse_options);
1787 DLLLOCAL
void exportGlobalVariable(
const char* name,
bool readonly, qore_program_private& tpgm,
ExceptionSink* xsink);
1794 DLLLOCAL
void setThreadTZ(ThreadProgramData* tpd,
const AbstractQoreZoneInfo* tz) {
1796 pgm_data_map_t::iterator i = pgm_data_map.find(tpd);
1797 assert(i != pgm_data_map.end());
1798 i->second->setTZ(tz);
1801 DLLLOCAL
const AbstractQoreZoneInfo* getThreadTZ(ThreadProgramData* tpd,
bool& set)
const {
1803 pgm_data_map_t::const_iterator i = pgm_data_map.find(tpd);
1804 assert(i != pgm_data_map.end());
1805 set = i->second->tz_set;
1806 return i->second->tz;
1809 DLLLOCAL
void clearThreadTZ(ThreadProgramData* tpd) {
1811 pgm_data_map_t::iterator i = pgm_data_map.find(tpd);
1812 assert(i != pgm_data_map.end());
1813 i->second->clearTZ();
1816 DLLLOCAL
void addStatement(AbstractStatement* s);
1820 return parseExpression(source, label, xsink);
1824 ProgramThreadCountContextHelper pch(xsink, pgm,
true);
1828 if (exp_set.find(exp) == exp_set.end()) {
1829 xsink->
raiseException(
"INVALID-EXPRESSION",
"expression not registered to this Program object");
1832 ThreadFrameBoundaryHelper tfbh(
true);
1838 return rv.release();
1841 DLLLOCAL
void deleteExpression(q_exp_t exp) {
1843 q_exp_set_t::iterator i = exp_set.find(exp);
1844 if (i != exp_set.end()) {
1850 DLLLOCAL
void importClass(
ExceptionSink* xsink, qore_program_private& from_pgm,
const char* path,
const char* new_name =
nullptr,
bool inject =
false, q_setpub_t set_pub = CSP_UNCHANGED);
1852 DLLLOCAL
void importHashDecl(
ExceptionSink* xsink, qore_program_private& from_pgm,
const char* path,
const char* new_name =
nullptr, q_setpub_t set_pub = CSP_UNCHANGED);
1854 DLLLOCAL
const char* addString(
const char* str) {
1855 str_set_t::iterator i = str_set.lower_bound(str);
1856 if (i == str_set.end() || strcmp(*i, str)) {
1857 str_vec.push_back(strdup(str));
1858 i = str_set.insert(i, str_vec.back());
1863 DLLLOCAL
void addFile(
const char*& file) {
1864 file = addString(file);
1865 printd(5,
"qore_program_private::addFile('%s')\n", file);
1866 addStatementToIndexIntern(&statementByFileIndex, file,
nullptr, -1,
nullptr, -1);
1869 DLLLOCAL
void addFile(
const char*& file,
const char*& source,
int offset) {
1870 file = addString(file);
1872 source = addString(source);
1874 printd(5,
"qore_program_private::addFile('%s', '%s', %d)\n", file, source ? source :
"(null)", offset);
1875 addStatementToIndexIntern(&statementByFileIndex, file,
nullptr, -1, source, offset);
1877 addStatementToIndexIntern(&statementByLabelIndex, source,
nullptr, -1, file, offset);
1881 DLLLOCAL
int addFeature(
const char* f) {
1883 strset_t::iterator i = featureList.lower_bound(f);
1884 if (i != featureList.end() && (*i == f)) {
1888 featureList.insert(i, f);
1892 DLLLOCAL
void removeFeature(
const char* f) {
1893 strset_t::iterator i = featureList.find(f);
1894 assert(i != featureList.end());
1895 featureList.erase(i);
1898 DLLLOCAL
int addUserFeature(
const char* f) {
1900 strset_t::iterator i = userFeatureList.lower_bound(f);
1901 if (i != userFeatureList.end() && (*i == f)) {
1905 userFeatureList.insert(i, f);
1909 DLLLOCAL
bool hasUserFeature(
const std::string feature)
const {
1910 return userFeatureList.find(feature) != userFeatureList.end();
1913 DLLLOCAL
void removeUserFeature(
const char* f) {
1914 strset_t::iterator i = userFeatureList.find(f);
1915 assert(i != userFeatureList.end());
1916 userFeatureList.erase(i);
1919 DLLLOCAL
bool hasFeature(
const char* f)
const {
1920 return (featureList.find(f) != featureList.end())
1921 || (userFeatureList.find(f) != userFeatureList.end());
1924 DLLLOCAL
void runtimeImportSystemClassesIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1925 DLLLOCAL
void runtimeImportSystemConstantsIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1926 DLLLOCAL
void runtimeImportSystemFunctionsIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1927 DLLLOCAL
void runtimeImportSystemHashDeclsIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1929 DLLLOCAL
void runtimeImportSystemClasses(
ExceptionSink* xsink);
1930 DLLLOCAL
void runtimeImportSystemConstants(
ExceptionSink* xsink);
1931 DLLLOCAL
void runtimeImportSystemFunctions(
ExceptionSink* xsink);
1932 DLLLOCAL
void runtimeImportSystemHashDecls(
ExceptionSink* xsink);
1941 assert(extmap.find(owner) == extmap.end());
1942 extmap.insert(extmap_t::value_type(owner, pud));
1947 extmap_t::const_iterator i = extmap.find(owner);
1948 return i == extmap.end() ? nullptr : i->second;
1953 extmap_t::iterator i = extmap.find(owner);
1954 if (i == extmap.end()) {
1963 return qore_root_ns_private::getGlobalVars(*RootNS);
1966 DLLLOCAL LocalVar* createLocalVar(
const char* name,
const QoreTypeInfo* typeInfo);
1968 DLLLOCAL
const AbstractQoreFunctionVariant* runtimeFindCall(
const char* name,
const QoreListNode* params,
ExceptionSink* xsink);
1973 return pgm.priv->runtimeFindClass(class_name, xsink);
1977 pgm.priv->doThreadInit(xsink);
1982 if (!pgm.priv->exec_class) {
1983 xsink->
raiseException(
"SETRETURNVALUE-ERROR",
"cannot set return value when not running in %%exec-class mode; in this case simply return the value directly (or call exit(<val>))");
1986 pgm.priv->exec_class_rv.discard(xsink);
1987 pgm.priv->exec_class_rv = rv.release();
1993 return pgm.priv->preregisterNewThread(xsink);
1997 DLLLOCAL
static void cancelPreregistration(
QoreProgram& pgm) {
1998 pgm.priv->cancelPreregistration();
2002 DLLLOCAL
static void registerNewThread(
QoreProgram& pgm,
int tid) {
2003 pgm.priv->registerNewThread(tid);
2007 pgm.priv->runtimeImportSystemClasses(xsink);
2011 pgm.priv->runtimeImportSystemHashDecls(xsink);
2015 pgm.priv->runtimeImportSystemConstants(xsink);
2019 pgm.priv->runtimeImportSystemFunctions(xsink);
2023 pgm.priv->runtimeImportSystemApi(xsink);
2026 DLLLOCAL
static qore_program_private* get(
QoreProgram& pgm) {
2031 pgm.priv->clearThreadData(xsink);
2034 DLLLOCAL
static void addStatement(
QoreProgram& pgm, AbstractStatement* s) {
2035 pgm.priv->addStatement(s);
2038 DLLLOCAL
static const AbstractQoreZoneInfo* currentTZIntern(
QoreProgram& pgm) {
2039 return pgm.priv->TZ;
2043 return pgm.priv->lockParsing(xsink);
2046 DLLLOCAL
static void unlockParsing(
QoreProgram& pgm) {
2047 pgm.priv->unlockParsing();
2051 return pgm.priv->incThreadCount(xsink);
2054 DLLLOCAL
static void decThreadCount(
QoreProgram& pgm,
int tid) {
2055 pgm.priv->decThreadCount(tid);
2059 DLLLOCAL
static void addSignal(
QoreProgram& pgm,
int sig) {
2060 assert(pgm.priv->sigset.find(sig) == pgm.priv->sigset.end());
2061 pgm.priv->sigset.insert(sig);
2065 DLLLOCAL
static void delSignal(
QoreProgram& pgm,
int sig) {
2066 assert(pgm.priv->sigset.find(sig) != pgm.priv->sigset.end());
2067 pgm.priv->sigset.erase(sig);
2071 pgm.priv->qore_program_private_base::startThread(xsink);
2076 return pgm.priv->setThreadInit(n_thr_init, xsink);
2081 return pgm->priv->runtimeGetCallReference(name, xsink);
2084 DLLLOCAL
static const ParseWarnOptions& getParseWarnOptions(
const QoreProgram* pgm) {
2085 return pgm->priv->pwo;
2088 DLLLOCAL
static bool setSaveParseWarnOptions(
const QoreProgram* pgm,
const ParseWarnOptions &new_opts,
2089 ParseWarnOptions &old_opts) {
2090 if (new_opts == pgm->priv->pwo)
2092 old_opts = pgm->priv->pwo;
2093 pgm->priv->pwo = new_opts;
2097 DLLLOCAL
static void setParseWarnOptions(
const QoreProgram* pgm,
const ParseWarnOptions &new_opts) {
2098 pgm->priv->pwo = new_opts;
2101 DLLLOCAL
static bool setThreadVarData(
QoreProgram* pgm, ThreadProgramData* td, ThreadLocalProgramData* &tlpd,
2103 return pgm->priv->setThreadVarData(td, tlpd, run);
2107 pgm->priv->makeParseException(loc,
"PARSE-EXCEPTION", desc);
2110 DLLLOCAL
static void makeParseException(
QoreProgram* pgm,
const QoreProgramLocation &loc,
const char* err,
2112 pgm->priv->makeParseException(loc, err, desc);
2117 return pgm->priv->getDefine(name, is_defined);
2120 DLLLOCAL
static const QoreValue parseGetDefine(
QoreProgram* pgm,
const char* name,
bool& is_defined) {
2121 return pgm->priv->getDefine(name, is_defined);
2126 return pgm->priv->runTimeGetDefine(name, is_defined);
2129 DLLLOCAL
static QoreValue runTimeGetDefine(
QoreProgram* pgm,
const char* name,
bool& is_defined) {
2130 return pgm->priv->runTimeGetDefine(name, is_defined);
2134 return pgm->priv->runTimeGetAllDefines();
2137 DLLLOCAL
static bool parseUnDefine(
QoreProgram* pgm,
const char* name) {
2138 return pgm->priv->parseUnDefine(name);
2142 return pgm->priv->runTimeUnDefine(name, xsink);
2145 DLLLOCAL
static bool parseIsDefined(
QoreProgram* pgm,
const char* name) {
2146 return pgm->priv->isDefined(name);
2149 DLLLOCAL
static bool runTimeIsDefined(
QoreProgram* pgm,
const char* name) {
2150 return pgm->priv->runTimeIsDefined(name);
2153 DLLLOCAL
static void parseDefine(
QoreProgram* pgm,
const QoreProgramLocation* loc,
const char* str,
2155 pgm->priv->parseDefine(loc, str, val);
2159 pgm->priv->runTimeDefine(str, val, xsink);
2163 const QoreProgramLocation* loc =
nullptr) {
2165 pgm->priv->addParseException(*xsink, loc);
2170 const QoreProgramLocation* loc =
nullptr) {
2171 pgm->priv->addParseException(xsink, loc);
2175 const char* name,
const char* new_name =
nullptr,
bool inject =
false) {
2176 srcpgm->priv->exportFunction(xsink, trgpgm->priv, name, new_name, inject);
2180 return pgm->priv->parseAddDomain(n_dom);
2184 return pgm.priv->dom;
2188 pgm.priv->dom |= n_dom;
2192 int64 rv = pgm.priv->pwo.parse_options;
2193 pgm.priv->pwo.parse_options = po;
2197 DLLLOCAL
static void makeParseWarning(
QoreProgram* pgm,
const QoreProgramLocation &loc,
int code,
2198 const char* warn,
const char* fmt, ...) {
2202 if (!pgm->priv->warnSink || !(code & pgm->priv->pwo.warn_mask)) {
2209 va_start(args, fmt);
2210 int rc = desc->
vsprintf(fmt, args);
2215 QoreException *ne =
new ParseException(loc, warn, desc);
2216 pgm->priv->warnSink->raiseException(ne);
2219 DLLLOCAL
static void makeParseWarning(
QoreProgram* pgm,
const QoreProgramLocation& loc,
int code,
2224 if (!pgm->priv->warnSink || !(code & pgm->priv->pwo.warn_mask)) {
2229 QoreException *ne =
new ParseException(loc, warn, desc);
2230 pgm->priv->warnSink->raiseException(ne);
2233 DLLLOCAL
static void exportGlobalVariable(
QoreProgram* pgm,
const char* name,
bool readonly,
QoreProgram* tpgm,
2235 pgm->priv->exportGlobalVariable(name, readonly, *(tpgm->priv), xsink);
2238 DLLLOCAL
void attachDebug(
const qore_debug_program_private* n_dpgm) {
2239 printd(5,
"qore_program_private::attachDebug(n_dpgm: %p), dpgm: %p\n", n_dpgm, dpgm);
2245 dpgm =
const_cast<qore_debug_program_private*
>(n_dpgm);
2246 printd(5,
"qore_program_private::attachDebug, dpgm: %p, pgm_data_map: size:%d, begin: %p, end: %p\n", dpgm,
2247 pgm_data_map.size(), pgm_data_map.begin(), pgm_data_map.end());
2248 for (
auto& i : pgm_data_map) {
2249 i.second->dbgPendingAttach();
2250 i.second->dbgBreak();
2254 DLLLOCAL
void detachDebug(
const qore_debug_program_private* n_dpgm) {
2255 printd(5,
"qore_program_private::detachDebug(n_dpgm: %p), dpgm: %p\n", n_dpgm, dpgm);
2258 assert(n_dpgm==dpgm);
2262 printd(5,
"qore_program_private::detachDebug, dpgm: %p, pgm_data_map: size:%d, begin: %p, end: %p\n", dpgm,
2263 pgm_data_map.size(), pgm_data_map.begin(), pgm_data_map.end());
2264 for (
auto& i : pgm_data_map) {
2265 i.second->dbgPendingDetach();
2271 DLLLOCAL
void onAttach(DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink);
2272 DLLLOCAL
void onDetach(DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink);
2273 DLLLOCAL
void onStep(
const StatementBlock* blockStatement,
const AbstractStatement* statement,
unsigned bkptId,
int& flow, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink);
2274 DLLLOCAL
void onFunctionEnter(
const StatementBlock* statement, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink);
2275 DLLLOCAL
void onFunctionExit(
const StatementBlock* statement,
QoreValue& returnValue, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink);
2276 DLLLOCAL
void onException(
const AbstractStatement* statement, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink);
2277 DLLLOCAL
void onExit(
const StatementBlock* statement,
QoreValue& returnValue, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink);
2279 DLLLOCAL
int breakProgramThread(
int tid) {
2280 printd(5,
"qore_program_private::breakProgramThread(), this: %p, tid: %d\n",
this,
q_gettid());
2282 for (
auto& i : pgm_data_map) {
2283 if (i.first->gettid() == tid) {
2284 i.second->dbgBreak();
2291 DLLLOCAL
void breakProgram() {
2292 printd(5,
"qore_program_private::breakProgram(), this: %p\n",
this);
2294 for (
auto& i : pgm_data_map) {
2295 i.second->dbgBreak();
2300 if (!bkpt ||
this == bkpt->pgm)
return;
2301 if (!checkAllowDebugging(xsink))
2307 breakpointList.push_back(bkpt);
2312 DLLLOCAL
void deleteAllBreakpoints() {
2314 for (QoreBreakpointList_t::iterator it = breakpointList.begin(); it != breakpointList.end(); ++it) {
2315 (*it)->unassignAllStatements();
2316 (*it)->pgm =
nullptr;
2319 breakpointList.clear();
2322 DLLLOCAL
void getBreakpoints(QoreBreakpointList_t &bkptList) {
2325 for (QoreBreakpointList_t::iterator it = breakpointList.begin(); it != breakpointList.end(); ++it) {
2326 bkptList.push_back(*it);
2331 DLLLOCAL
void getStatementBreakpoints(
const AbstractStatement* statement, QoreBreakpointList_t &bkptList) {
2334 if (statement->breakpoints) {
2335 for (std::list<QoreBreakpoint*>::iterator it = statement->breakpoints->begin(); it != statement->breakpoints->end(); ++it) {
2336 bkptList.push_back(*it);
2342 DLLLOCAL
inline unsigned onCheckBreakpoint(
const AbstractStatement* statement,
ExceptionSink* xsink) {
2352 DLLLOCAL
unsigned long getStatementId(
const AbstractStatement* statement)
const {
2356 ReverseStatementIdMap_t::const_iterator i = reverseStatementIds.find((AbstractStatement*) statement);
2357 if (i == reverseStatementIds.end())
2362 DLLLOCAL AbstractStatement* resolveStatementId(
unsigned long statementId)
const {
2364 if (statementId == 0 || statementId > statementIds.size())
2366 return statementIds[statementId-1];
2369 DLLLOCAL
unsigned getProgramId()
const {
2382 qore_root_ns_private::clearData(*RootNS, xsink);
2385 DLLLOCAL
static QoreProgram* resolveProgramId(
unsigned programId) {
2386 printd(5,
"qore_program_private::resolveProgramId(%x)\n", programId);
2388 for (qore_program_to_object_map_t::iterator i = qore_program_to_object_map.begin(); i != qore_program_to_object_map.end(); i++) {
2389 if (i->first->priv->programId == programId)
2398 xsink->
raiseException(
"DEBUGGING",
"program does not provide internal data for debugging");
2406 DLLLOCAL
void addStatementToIndexIntern(name_section_sline_statement_map_t* statementIndex,
const char* key, AbstractStatement* statement,
int offs,
const char* section,
int sectionOffs);
2407 DLLLOCAL
static void registerStatement(
QoreProgram* pgm, AbstractStatement* statement,
bool addToIndex);
2408 DLLLOCAL
QoreHashNode* getSourceIndicesIntern(name_section_sline_statement_map_t* statementIndex,
ExceptionSink* xsink)
const;
2410 return getSourceIndicesIntern(&statementByLabelIndex, xsink);
2413 return getSourceIndicesIntern(&statementByFileIndex, xsink);
2416 DLLLOCAL AbstractStatement* getStatementFromIndex(
const char* name,
int line) {
2417 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d), this: %p, file#: %d, label#: %d\n", name, line,
this, statementByFileIndex.size(), statementByLabelIndex.size());
2419 name_section_sline_statement_map_t::iterator it;
2420 if (statementByFileIndex.empty()) {
2423 bool addOffs =
true;
2424 if (!name || *name ==
'\0') {
2425 if (statementByFileIndex.size() != 1)
2427 it = statementByFileIndex.begin();
2429 size_t l = strlen(name);
2430 it = statementByFileIndex.find(name);
2431 if (it == statementByFileIndex.end()) {
2432 it = statementByLabelIndex.find(name);
2433 if (it == statementByLabelIndex.end()) {
2436 it = statementByFileIndex.begin();
2437 while (it != statementByFileIndex.end()) {
2438 size_t k = strlen(it->first);
2440 if (strcmp(name, it->first + k - l) == 0) {
2442 if (k == l || name[0] ==
'/' || it->first[k-l-1] ==
'/') {
2449 if (it == statementByFileIndex.end()) {
2450 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) no suffix match, this: %p\n", name, line,
this);
2453 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found by file suffix match, this: %p\n", name, line,
this);
2456 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found by label full match, this: %p\n", name, line,
this);
2459 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found by file full match, this: %p\n", name, line,
this);
2462 sline_statement_map_t *ssm = &it->second->statementMap;
2463 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found '%s', this: %p, ssm#: %d\n", name, line, it->first,
this, ssm->size());
2464 if (ssm->size() == 0)
2467 sline_statement_map_t::iterator li = ssm->upper_bound(line);
2468 if (li == ssm->begin()) {
2469 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) no statement found by line #1, this: %p\n", name, line,
this);
2475 AbstractStatement* st =
nullptr;
2478 if (ln != li->first) {
2482 if (li->second->loc->start_line + (addOffs ? li->second->loc->offset : 0) <= line && li->second->loc->end_line + (addOffs ? li->second->loc->offset : 0) >= line) {
2483 int n = li->second->loc->end_line - li->second->loc->start_line;
2496 if (li == ssm->begin())
2501 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) statement:('file':%s,source:%s,offset:%d,line:%d-%d), this: %p\n", name, line, st->loc->getFile(), st->loc->getSource(), st->loc->offset, st->loc->start_line, st->loc->end_line,
this);
2503 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) no statement found by line #2, this: %p\n", name, line,
this);
2509 printd(5,
"qore_program_private::registerQoreObject() pgm: %p, pgmid: %d\n", pgm, getProgramId());
2511 qore_program_to_object_map_t::iterator i = qore_program_private::qore_program_to_object_map.find(pgm);
2512 assert(i != qore_program_private::qore_program_to_object_map.end());
2513 if (i->second && i->second != o) {
2514 xsink->
raiseException(
"PROGRAM-ERROR",
"The Program has already assigned QoreObject");
2521 printd(5,
"qore_program_private::unregisterQoreObject() pgm: %p, pgmid: %d\n", pgm, getProgramId());
2523 qore_program_to_object_map_t::iterator i = qore_program_private::qore_program_to_object_map.find(pgm);
2524 assert(i != qore_program_private::qore_program_to_object_map.end());
2525 assert(i->second == o);
2526 i->second =
nullptr;
2531 qore_program_to_object_map_t::iterator i = qore_program_to_object_map.find(pgm);
2532 if (i == qore_program_to_object_map.end()) {
2544 qore_program_to_object_map_t::iterator i = qore_program_to_object_map.find(pgm);
2545 assert(i != qore_program_to_object_map.end());
2547 printd(5,
"qore_program_private::getQoreObject() pgm: %p, pgmid: %d, second: %p\n", i->first, i->first->getProgramId(), i->second);
2551 printd(5,
"qore_program_private::getQoreObject() pgm: %p, pgmid: %d, new second: %p\n", pgm, pgm->
getProgramId(), i->second);
2561 qore_program_to_object_map_t::iterator i = qore_program_to_object_map.begin();
2562 while (i != qore_program_to_object_map.end()) {
2564 printd(5,
"qore_program_private::getAllQoreObjects() pgm: %p, pgmid: %d, second: %p\n", i->first, i->first->getProgramId(), i->second);
2568 printd(5,
"qore_program_private::getAllQoreObjects() pgm: %p, pgmid: %d, new second: %p\n", i->first, i->first->getProgramId(), i->second);
2571 (*l)->push(i->second,
nullptr);
2580 const AbstractQoreZoneInfo* n_TZ = QTZM.getLocalZoneInfo()) {
2588 if (!pendingParseSink)
2594 qore_debug_program_private* dpgm =
nullptr;
2596 QoreBreakpointList_t breakpointList;
2599 name_section_sline_statement_map_t statementByFileIndex;
2600 name_section_sline_statement_map_t statementByLabelIndex;
2603 typedef std::vector<AbstractStatement*> StatementVector_t;
2604 StatementVector_t statementIds;
2607 typedef std::map<AbstractStatement*, unsigned long> ReverseStatementIdMap_t;
2608 ReverseStatementIdMap_t reverseStatementIds;
2616 DLLLOCAL qore_debug_program_private* getDebugProgram(AutoQoreCounterDec& ad) {
2619 qore_debug_program_private* ret = dpgm;
2628 DLLLOCAL
bool isBreakpointRegistered(
const QoreBreakpoint* bkpt)
const {
2629 return std::find(breakpointList.begin(), breakpointList.end(), bkpt) != breakpointList.end();
2633 typedef std::map<QoreProgram*, QoreObject*> qore_program_to_object_map_t;
2634 static qore_program_to_object_map_t qore_program_to_object_map;
2636 static volatile unsigned programIdCounter;
2640class ParseWarnHelper :
public ParseWarnOptions {
2644 DLLLOCAL ParseWarnHelper(
const ParseWarnOptions &new_opts) {
2646 restore = pgm ? qore_program_private::setSaveParseWarnOptions(pgm, new_opts, *
this) : false;
2648 DLLLOCAL ~ParseWarnHelper() {
2650 qore_program_private::setParseWarnOptions(
getProgram(), *
this);
2654typedef std::map<QoreProgram*, qore_program_private*> qore_program_map_t;
2657class qore_debug_program_private {
2659 DLLLOCAL qore_debug_program_private(
QoreDebugProgram* n_dpgm) : dpgm(n_dpgm) {}
2661 DLLLOCAL ~qore_debug_program_private() {
2662 assert(qore_program_map.empty());
2666 if (!pgm->priv->checkAllowDebugging(xsink))
2669 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2670 printd(5,
"qore_debug_program_private::addProgram(), this: %p, pgm: %p, i: %p, end: %p\n",
this, pgm, i,
2671 qore_program_map.end());
2672 if (i != qore_program_map.end())
2674 qore_program_map.insert(qore_program_map_t::value_type(pgm, pgm->priv));
2676 pgm->priv->attachDebug(
this);
2681 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2682 printd(5,
"qore_debug_program_private::removeProgram(), this: %p, pgm: %p, i: %p, end: %p\n",
this, pgm, i,
2683 qore_program_map.end());
2684 if (i == qore_program_map.end())
2686 pgm->priv->detachDebug(
this);
2687 qore_program_map.erase(i);
2692 DLLLOCAL
void removeAllPrograms() {
2694 printd(5,
"qore_debug_program_private::removeAllPrograms(), this: %p\n",
this);
2695 qore_program_map_t::iterator i;
2696 while ((i = qore_program_map.begin()) != qore_program_map.end()) {
2697 qore_program_private* qpp = i->second;
2699 qore_program_map.erase(i);
2700 qpp->detachDebug(
this);
2707 printd(5,
"qore_debug_program_private::getAllProgramObjects(), this: %p\n",
this);
2709 qore_program_map_t::iterator i = qore_program_map.begin();
2710 while (i != qore_program_map.end()) {
2713 (*l)->push(o,
nullptr);
2720 DLLLOCAL
void onAttach(
QoreProgram* pgm, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
2722 AutoQoreCounterDec ad(&debug_program_counter);
2723 dpgm->onAttach(pgm, rs, rts, xsink);
2726 DLLLOCAL
void onDetach(
QoreProgram* pgm, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
2728 AutoQoreCounterDec ad(&debug_program_counter);
2729 dpgm->onDetach(pgm, rs, rts, xsink);
2739 DLLLOCAL
void onStep(
QoreProgram* pgm,
const StatementBlock* blockStatement,
const AbstractStatement* statement,
2740 unsigned bkptId,
int& flow, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink) {
2741 AutoQoreCounterDec ad(&debug_program_counter);
2742 dpgm->onStep(pgm, blockStatement, statement, bkptId, flow, rs, rts, xsink);
2745 DLLLOCAL
void onFunctionEnter(
QoreProgram* pgm,
const StatementBlock* statement, DebugRunStateEnum& rs,
2747 AutoQoreCounterDec ad(&debug_program_counter);
2748 dpgm->onFunctionEnter(pgm, statement, rs, rts, xsink);
2754 DLLLOCAL
void onFunctionExit(
QoreProgram* pgm,
const StatementBlock* statement,
QoreValue& returnValue,
2755 DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink) {
2756 AutoQoreCounterDec ad(&debug_program_counter);
2757 dpgm->onFunctionExit(pgm, statement, returnValue, rs, rts, xsink);
2762 DLLLOCAL
void onException(
QoreProgram* pgm,
const AbstractStatement* statement, DebugRunStateEnum& rs,
2764 AutoQoreCounterDec ad(&debug_program_counter);
2765 dpgm->onException(pgm, statement, rs, rts, xsink);
2770 DLLLOCAL
void onExit(
QoreProgram* pgm,
const StatementBlock* statement,
QoreValue& returnValue,
2771 DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink) {
2772 AutoQoreCounterDec ad(&debug_program_counter);
2773 dpgm->onExit(pgm, statement, returnValue, rs, rts, xsink);
2776 DLLLOCAL
int breakProgramThread(
QoreProgram* pgm,
int tid) {
2783 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2784 printd(5,
"qore_debug_program_private::breakProgramThread(), this: %p, pgm: %p, i: %p, end: %p, tid: %d\n",
2785 this, pgm, i, qore_program_map.end(), tid);
2786 if (i == qore_program_map.end())
2788 if (i->second->breakProgramThread(tid))
2800 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2801 printd(5,
"qore_debug_program_private::breakProgram(), this: %p, pgm: %p, i: %p, end: %p\n",
this, pgm, i,
2802 qore_program_map.end());
2803 if (i == qore_program_map.end())
2805 i->second->breakProgram();
2809 DLLLOCAL
void waitForTerminationAndClear(
ExceptionSink* xsink) {
2810 removeAllPrograms();
2815 DLLLOCAL
int getInterruptedCount() {
2816 return debug_program_counter.
getCount();
2823 qore_program_map_t qore_program_map;
DLLEXPORT const QoreEncoding * QCS_DEFAULT
the default encoding for the Qore library
DLLEXPORT char * q_basenameptr(const char *path)
returns a pointer within the same string
#define PO_NO_LOCALE_CONTROL
do not allow changes to program locale
Definition: Restrictions.h:64
#define PO_NO_CHILD_PO_RESTRICTIONS
turn off parse option inheritance restrictions
Definition: Restrictions.h:51
#define PO_ALLOW_INJECTION
allow code injection
Definition: Restrictions.h:76
#define PO_POSITIVE_OPTIONS
mask of all options allowing for more freedom (instead of less)
Definition: Restrictions.h:135
#define PO_FREE_OPTIONS
mask of options that have no effect on code access or code safety
Definition: Restrictions.h:139
#define PO_NO_DEBUGGING
disallows debugging actions that could be insecure such as reading the thread local variable stack
Definition: Restrictions.h:86
DLLLOCAL void ref() const
increments the reference count of the object
Definition: AbstractPrivateData.h:51
DLLEXPORT void deref(ExceptionSink *xsink)
decrements the reference count and calls derefImpl() if there_can_be_only_one is false,...
an abstract class for program-specific external data
Definition: QoreProgram.h:1001
provides a safe and exception-safe way to hold locks in Qore, only to be used on the stack,...
Definition: QoreThreadLock.h:136
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:50
DLLEXPORT void assimilate(ExceptionSink *xs)
assimilates all entries of the "xs" argument by appending them to the internal list and deletes the "...
DLLEXPORT AbstractQoreNode * raiseException(const char *err, const char *fmt,...)
appends a Qore-language exception to the list
DLLEXPORT AbstractQoreNode * raiseErrnoException(const char *err, int en, const char *fmt,...)
appends a Qore-language exception to the list and appends the result of strerror(errno) to the descri...
DLLEXPORT void clear()
deletes the exception list immediately
DLLEXPORT bool isException() const
returns true if at least one exception is present
provides a safe and exception-safe way to hold read locks in Qore, only to be used on the stack,...
Definition: QoreRWLock.h:105
provides a safe and exception-safe way to hold write locks in Qore, only to be used on the stack,...
Definition: QoreRWLock.h:144
Class implementing breakpoint for debugging.
Definition: QoreProgram.h:1040
DLLEXPORT unsigned getBreakpointId() const
get the breakpoint id
DLLEXPORT void assignProgram(QoreProgram *new_pgm, ExceptionSink *xsink)
defines a Qore-language class
Definition: QoreClass.h:253
DLLEXPORT const QoreTypeInfo * getTypeInfo() const
returns the type information structure for this class
a thread condition class implementing a wrapper for pthread_cond_t
Definition: QoreCondition.h:45
DLLEXPORT int wait(pthread_mutex_t *m)
blocks a thread on a mutex until the condition is signaled
DLLEXPORT int broadcast()
singles all threads blocked on this condition to wake up
a simple thread-safe counter object; objects can block on it until the counter reaches zero
Definition: QoreCounter.h:40
DLLEXPORT int getCount() const
returns the current count
DLLEXPORT int waitForZero(ExceptionSink *xsink, int timeout_ms=0)
blocks the calling thread until the counter reaches 0
supports parsing and executing Qore-language code, reference counted, dynamically-allocated only
Definition: QoreDebugProgram.h:66
This is the hash or associative list container type in Qore, dynamically allocated only,...
Definition: QoreHashNode.h:50
DLLEXPORT size_t size() const
returns the number of members in the hash, executes in constant time
DLLEXPORT QoreHashNode * copy() const
performs a copy of the hash and returns the new hash
This is the list container type in Qore, dynamically allocated only, reference counted.
Definition: QoreListNode.h:52
DLLEXPORT int push(QoreValue val, ExceptionSink *xsink)
adds a value to the list
DLLEXPORT QoreListNode * copy() const
performs a deep copy of the list and returns the new list
contains constants, classes, and subnamespaces in QoreProgram objects
Definition: QoreNamespace.h:65
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:128
static DLLEXPORT QoreObject * getQoreObject(QoreProgram *pgm)
get QoreObject of QoreProgram
DLLEXPORT unsigned getProgramId() const
get the program id
virtual DLLEXPORT void deref(ExceptionSink *xsink)
decrements the reference count of the object
provides a simple POSIX-threads-based read-write lock
Definition: QoreRWLock.h:47
provides atomic reference counting to Qore objects
Definition: QoreReferenceCounter.h:44
DLLEXPORT void ROreference() const
atomically increments the reference count
DLLEXPORT int reference_count() const
gets the reference count
DLLEXPORT bool ROdereference() const
atomically decrements the reference count
abstract base class for c++ Exceptions in the Qore library
Definition: QoreStandardException.h:49
Qore's string type supported by the QoreEncoding class.
Definition: QoreString.h:93
DLLEXPORT const char * c_str() const
returns the string's buffer; this data should not be changed
DLLEXPORT size_t strlen() const
returns number of bytes in the string (not including the null pointer)
DLLEXPORT bool empty() const
returns true if the string is empty, false if not
DLLEXPORT int vsprintf(const char *fmt, va_list args)
this will concatentate a formatted string to the existing string according to the format string and t...
Qore's string value type, reference counted, dynamically-allocated only.
Definition: QoreStringNode.h:50
provides access to thread-local storage
Definition: QoreThreadLocalStorage.h:44
DLLLOCAL void set(T *ptr)
sets the key's value
Definition: QoreThreadLocalStorage.h:82
DLLLOCAL T * get()
retrieves the key's value
Definition: QoreThreadLocalStorage.h:77
provides a mutually-exclusive thread lock
Definition: QoreThreadLock.h:49
a templated class to manage a reference count of an object that can throw a Qore-language exception w...
Definition: ReferenceHolder.h:52
base class for resolved call references
Definition: CallReferenceNode.h:109
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
provides an exception-safe way to manage locks in Qore, only to be used on the stack,...
Definition: QoreThreadLock.h:228
Private data for the Qore::StreamReader class.
Definition: StreamReader.h:45
Private data for the Qore::StreamWriter class.
Definition: StreamWriter.h:43
use this class to manage strings where the character encoding must be specified and may be different ...
Definition: QoreString.h:1125
DLLLOCAL int set(const QoreString *s, const QoreEncoding *qe, ExceptionSink *xsink)
discards any current state and sets and converts (if necessary) a new string to the desired encoding
Definition: QoreString.h:1166
typed hash declaration
Definition: TypedHashDecl.h:44
holds an object and dereferences it in the destructor
Definition: QoreValue.h:487
non-thread-safe vector for storing "char*" that you want to delete
Definition: common.h:238
std::set< int > int_set_t
set of integers
Definition: common.h:82
long long int64
64bit integer type, cannot use int64_t here since it breaks the API on some 64-bit systems due to equ...
Definition: common.h:260
DLLEXPORT QoreProgram * getProgram()
returns the current QoreProgram
DLLEXPORT const AbstractQoreZoneInfo * currentTZ()
returns the current local time zone, note that if 0 = UTC
DLLEXPORT int q_gettid() noexcept
returns the current TID number
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:276