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/QoreDebugProgram.h"
48 #include "qore/QoreRWLock.h"
49 #include "qore/vector_map"
50 #include "qore/vector_set"
57 typedef vector_map_t<int, unsigned> ptid_map_t;
60 typedef std::vector<AbstractStatement*> stmt_vec_t;
62 class QoreParseLocationHelper {
64 DLLLOCAL QoreParseLocationHelper(
const char* file,
const char* src,
int offset) {
65 thread_set_class_and_ns(
nullptr,
nullptr, cls, ns);
66 beginParsing(file,
nullptr, src, offset);
69 DLLLOCAL ~QoreParseLocationHelper() {
71 thread_set_class_and_ns(cls, ns);
76 const qore_class_private* cls;
80 class CharPtrList :
public safe_dslist<std::string> {
84 DLLLOCAL
bool find(
const char* str)
const {
85 const_iterator i = begin();
97 typedef safe_dslist<LocalVar*> local_var_list_t;
100 typedef StatementBlock* q_exp_t;
102 class LocalVariableList :
public local_var_list_t {
104 DLLLOCAL LocalVariableList() {
107 DLLLOCAL ~LocalVariableList() {
108 for (local_var_list_t::iterator i = begin(), e = end(); i != e; ++i) {
116 #include "qore/intern/ThreadLocalVariableData.h"
117 #include "qore/intern/ThreadClosureVariableStack.h"
119 hashdecl ThreadLocalProgramData {
122 DLLLOCAL ThreadLocalProgramData(
const ThreadLocalProgramData& old) =
delete;
125 DebugRunStateEnum runState = DBG_RS_DETACH;
127 const AbstractStatement* runToStatement =
nullptr;
129 int functionCallLevel = 0;
131 DLLLOCAL
inline void setRunState(DebugRunStateEnum rs,
const AbstractStatement* rts) {
132 assert(rs < DBG_RS_STOPPED);
133 if (rs == DBG_RS_UNTIL_RETURN) {
134 functionCallLevel = 1;
136 printd(5,
"ThreadLocalProgramData::setRunState(), this: %p, rs: %d->%d, rts: %p\n",
this, runState, rs, rts);
138 runToStatement = rts;
141 volatile bool breakFlag =
false;
143 DLLLOCAL
inline void checkBreakFlag() {
144 if (breakFlag && runState != DBG_RS_DETACH) {
146 if (runState != DBG_RS_STOPPED) {
147 runState = DBG_RS_STEP;
149 printd(5,
"ThreadLocalProgramData::checkBreakFlag(), this: %p, rs: %d\n",
this, runState);
155 if (runState != DBG_RS_STOPPED) {
156 if (attachFlag > 0) {
161 }
else if (attachFlag < 0) {
170 ThreadLocalVariableData lvstack;
172 ThreadClosureVariableStack cvstack;
174 const AbstractQoreZoneInfo* tz =
nullptr;
181 DLLLOCAL ThreadLocalProgramData() : tz_set(false), inst(false) {
182 printd(5,
"ThreadLocalProgramData::ThreadLocalProgramData() this: %p\n",
this);
185 DLLLOCAL ~ThreadLocalProgramData() {
186 printd(5,
"ThreadLocalProgramData::~ThreadLocalProgramData() this: %p, rs: %d\n",
this, runState);
187 assert(lvstack.empty());
188 assert(cvstack.empty());
192 lvstack.finalize(sdh);
193 cvstack.finalize(sdh);
202 DLLLOCAL
void setTZ(
const AbstractQoreZoneInfo* n_tz) {
207 DLLLOCAL
void clearTZ() {
245 DLLLOCAL
int dbgStep(
const StatementBlock* blockStatement,
const AbstractStatement* statement,
ExceptionSink* xsink);
249 DLLLOCAL
void dbgFunctionEnter(
const StatementBlock* statement,
ExceptionSink* xsink);
253 DLLLOCAL
void dbgFunctionExit(
const StatementBlock* statement,
QoreValue& returnValue,
ExceptionSink* xsink);
257 DLLLOCAL
void dbgException(
const AbstractStatement* statement,
ExceptionSink* xsink);
266 DLLLOCAL
void dbgBreak() {
267 printd(5,
"ThreadLocalProgramData::dbgBreak(), this: %p\n",
this);
273 DLLLOCAL
void dbgPendingAttach() {
274 printd(5,
"ThreadLocalProgramData::dbgPendingAttach(), this: %p\n",
this);
280 DLLLOCAL
void dbgPendingDetach() {
281 printd(5,
"ThreadLocalProgramData::dbgPendingDetach(), this: %p\n",
this);
288 DLLLOCAL
bool dbgIsAttached() {
289 return runState != DBG_RS_DETACH;
294 typedef vector_map_t<ThreadProgramData*, ThreadLocalProgramData*> pgm_data_map_t;
298 typedef vector_map_t<std::string, QoreValue> dmap_t;
302 typedef vector_map_t<const char*, int64> ppo_t;
305 class AbstractQoreZoneInfo;
309 DLLLOCAL
bool operator()(
const QoreProgramLocation* p1,
const QoreProgramLocation* p2)
const {
317 hashdecl pgmloc_vec_t :
public std::vector<QoreProgramLocation*> {
318 DLLLOCAL ~pgmloc_vec_t() {
322 DLLLOCAL
void clear() {
323 for (
auto& i : *
this) {
327 std::vector<QoreProgramLocation*>::clear();
331 class qore_program_private_base {
332 friend class QoreProgramAccessHelper;
335 DLLLOCAL
void setDefines();
337 typedef vector_map_t<const char*, AbstractQoreProgramExternalData*> extmap_t;
342 LocalVariableList local_var_list;
347 unsigned thread_count;
348 unsigned thread_waiting;
349 unsigned parse_count;
358 typedef std::set<const char*, ltstr> str_set_t;
362 typedef std::set<const QoreProgramLocation*, ltpgm> loc_set_t;
366 CharPtrList featureList;
368 CharPtrList userFeatureList;
383 TopLevelStatementBlock sb;
386 bool only_first_except : 1,
388 po_allow_restrict : 1,
391 requires_exception : 1,
393 parsing_in_progress : 1,
399 typedef std::set<q_exp_t> q_exp_set_t;
401 q_exp_t new_expression =
nullptr;
405 int exceptions_raised,
408 ParseWarnOptions pwo;
413 std::string exec_class_name, script_dir, script_path, script_name, include_path;
420 mutable unsigned twaiting;
423 pgm_data_map_t pgm_data_map;
426 const AbstractQoreZoneInfo* TZ;
444 : thread_count(0), thread_waiting(0), parse_count(0), plock(&ma_recursive), parseSink(nullptr), warnSink(nullptr), pendingParseSink(nullptr), RootNS(nullptr), QoreNS(nullptr),
446 only_first_except(false), po_locked(false), po_allow_restrict(true), exec_class(false), base_object(false),
447 requires_exception(false),
449 parsing_in_progress(false),
452 expression_mode(false),
454 exceptions_raised(0), ptid(0), pwo(n_parse_options), dom(0), pend_dom(0), thread_local_storage(nullptr), twaiting(0),
455 thr_init(nullptr), pgm(n_pgm) {
456 printd(QPP_DBG_LVL,
"qore_program_private_base::qore_program_private_base() this: %p pgm: %p po: " QLLD
"\n",
this, pgm, n_parse_options);
459 pgm->priv = (qore_program_private*)
this;
462 setParent(p_pgm, n_parse_options);
464 TZ = QTZM.getLocalZoneInfo();
469 Var *var = qore_root_ns_private::runtimeCreateVar(*RootNS, *QoreNS,
"ARGV", listTypeInfo,
true);
471 var->setInitial(ARGV->
copy());
473 var = qore_root_ns_private::runtimeCreateVar(*RootNS, *QoreNS,
"QORE_ARGV", listTypeInfo,
true);
474 if (var && QORE_ARGV)
475 var->setInitial(QORE_ARGV->
copy());
477 var = qore_root_ns_private::runtimeCreateVar(*RootNS, *QoreNS,
"ENV", hashTypeInfo,
true);
479 var->setInitial(ENV->
copy());
484 DLLLOCAL ~qore_program_private_base() {
485 printd(QPP_DBG_LVL,
"qore_program_private_base::~qore_program_private_base() this: %p pgm: %p\n",
this, pgm);
489 DLLLOCAL
const QoreProgramLocation* getLocation(
int sline,
int eline);
490 DLLLOCAL
const QoreProgramLocation* getLocation(
const QoreProgramLocation&,
int sline,
int eline);
498 DLLLOCAL
void newProgram();
501 class PreParseHelper {
503 qore_program_private_base *p;
507 DLLLOCAL PreParseHelper(qore_program_private_base *n_p) : p(n_p), swapped(false) {
509 if (!p->pendingParseSink)
511 p->parseSink = p->pendingParseSink;
516 DLLLOCAL ~PreParseHelper() {
518 p->parseSink =
nullptr;
522 class qore_debug_program_private;
524 class AutoQoreCounterDec {
528 AutoQoreCounterDec() {}
530 AutoQoreCounterDec(
QoreCounter* n_cnt,
bool incNow =
true): cnt(n_cnt), incFlag(false) {
535 ~AutoQoreCounterDec() {
547 class qore_program_private :
public qore_program_private_base {
550 DLLLOCAL
void init(
QoreProgram* n_pgm,
int64 n_parse_options,
const AbstractQoreZoneInfo* n_TZ = QTZM.getLocalZoneInfo()) {
558 if (!pendingParseSink)
564 qore_debug_program_private* dpgm;
566 QoreBreakpointList_t breakpointList;
569 typedef std::map<int, AbstractStatement*> sline_statement_map_t;
571 typedef std::map<const char*, int, ltstr> section_offset_map_t;
573 hashdecl section_sline_statement_map {
574 section_offset_map_t sectionMap;
575 sline_statement_map_t statementMap;
578 typedef section_sline_statement_map section_sline_statement_map_t;
581 typedef vector_map_t<const char*, section_sline_statement_map_t*> name_section_sline_statement_map_t;
585 name_section_sline_statement_map_t statementByFileIndex;
586 name_section_sline_statement_map_t statementByLabelIndex;
589 typedef std::vector<AbstractStatement*> StatementVector_t;
590 StatementVector_t statementIds;
593 typedef std::map<AbstractStatement*, unsigned long> ReverseStatementIdMap_t;
594 ReverseStatementIdMap_t reverseStatementIds;
601 DLLLOCAL qore_debug_program_private* getDebugProgram(AutoQoreCounterDec& ad) {
604 qore_debug_program_private* ret = dpgm;
613 DLLLOCAL
bool isBreakpointRegistered(
const QoreBreakpoint *bkpt)
const {
614 return std::find(breakpointList.begin(), breakpointList.end(), bkpt) != breakpointList.end();
618 typedef std::map<QoreProgram*, QoreObject*> qore_program_to_object_map_t;
619 static qore_program_to_object_map_t qore_program_to_object_map;
621 static volatile unsigned programIdCounter;
627 DLLLOCAL ~qore_program_private();
629 DLLLOCAL
void depRef() {
634 DLLLOCAL
void depDeref() {
651 for (
auto& i : pgm_data_map) {
652 i.second->finalize(sdh);
658 for (
auto& i : pgm_data_map) {
659 i.second->del(xsink);
660 i.first->delProgram(pgm);
664 DLLLOCAL
void waitForTerminationAndClear(
ExceptionSink* xsink);
676 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed has already been deleted and therefore no new threads can be started in it");
685 DLLLOCAL
void cancelPreregistration() {
689 assert(thread_count > 0);
690 if (!--thread_count && thread_waiting)
695 DLLLOCAL
void registerNewThread(
int tid) {
699 assert(thread_count);
720 if (ptid && ptid != tid) {
721 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed has already been deleted and therefore cannot be accessed at runtime");
724 if (parsing_in_progress) {
725 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed is currently undergoing parsing and cannot be accessed at runtime");
734 DLLLOCAL
void incThreadCount() {
740 if (ptid && ptid != tid) {
741 throw QoreStandardException(
"PROGRAM-ERROR",
"the Program accessed has already been deleted and therefore cannot be accessed at runtime");
743 if (parsing_in_progress) {
744 throw QoreStandardException(
"PROGRAM-ERROR",
"the Program accessed is currently undergoing parsing and cannot be accessed at runtime");
751 DLLLOCAL
void decThreadCount(
int tid) {
755 ptid_map_t::iterator i = tidmap.find(tid);
756 assert(i != tidmap.end());
760 assert(thread_count > 0);
761 if (!--thread_count && thread_waiting)
770 for (
auto& i : tidmap) {
771 l.
push(i.first,
nullptr);
781 while (parse_count) {
790 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed has already been deleted and therefore cannot be accessed");
799 DLLLOCAL
void unlockParsing() {
802 if (!(--parse_count) && thread_waiting)
807 DLLLOCAL
void waitForAllThreadsToTerminateIntern() {
810 ptid_map_t::iterator i = tidmap.find(tid);
811 unsigned adj = (i != tidmap.end() ? 1 : 0);
813 while ((thread_count - adj) || parse_count) {
820 DLLLOCAL
void waitForAllThreadsToTerminate() {
823 waitForAllThreadsToTerminateIntern();
826 DLLLOCAL
const char* parseGetScriptPath()
const {
827 return script_path.empty() ? nullptr : script_path.c_str();
830 DLLLOCAL
const char* parseGetScriptDir()
const {
831 return script_dir.empty() ? nullptr : script_dir.c_str();
834 DLLLOCAL
const char* parseGetScriptName()
const {
835 return script_name.empty() ? nullptr : script_name.c_str();
841 return script_path.empty() ? nullptr :
new QoreStringNode(script_path);
847 return script_dir.empty() ? nullptr :
new QoreStringNode(script_dir);
853 return script_name.empty() ? nullptr :
new QoreStringNode(script_name);
856 DLLLOCAL
void setScriptPathExtern(
const char* path) {
862 DLLLOCAL
void setScriptPath(
const char* path) {
872 script_dir =
"." QORE_DIR_SEP_STR;
873 script_path = script_dir + script_name;
877 script_dir.assign(path, p - path);
892 for (CharPtrList::const_iterator i = featureList.begin(), e = featureList.end(); i != e; ++i)
895 for (CharPtrList::const_iterator i = userFeatureList.begin(), e = userFeatureList.end(); i != e; ++i)
904 DLLLOCAL
int internParsePending(
ExceptionSink* xsink,
const char* code,
const char* label,
const char* orig_src =
nullptr,
int offset = 0,
bool standard_parse =
true) {
907 assert(code && code[0]);
911 const char* sname = label;
912 const char* src = orig_src;
914 addFile(src, sname, offset);
919 QoreParseLocationHelper qplh(sname, src, offset);
926 beginParsing(sname,
nullptr, src, offset);
928 if (!parsing_in_progress) {
929 parsing_in_progress =
true;
938 yy_scan_string(code, lexer);
939 yyset_lineno(1, lexer);
943 printd(5,
"qore_program_private::internParsePending() returned from yyparse()\n");
947 if (standard_parse) {
948 printd(5,
"qore_program_private::internParsePending() parse exception: calling parseRollback()\n");
949 internParseRollback(xsink);
950 requires_exception =
false;
954 printd(5,
"qore_program_private::internParsePending() about to call yylex_destroy()\n");
955 yylex_destroy(lexer);
956 printd(5,
"qore_program_private::internParsePending() returned from yylex_destroy()\n");
965 if (pendingParseSink) {
967 pendingParseSink =
nullptr;
973 xsink->
raiseException(
"PARSE-ERROR",
"parsing can only happen once for each Program container");
979 DLLLOCAL
int parsePending(
const char* code,
const char* label,
ExceptionSink* xsink,
ExceptionSink* wS,
int wm,
const char* orig_src =
nullptr,
int offset = 0) {
982 ProgramRuntimeParseContextHelper pch(xsink, pgm);
988 if (checkParse(xsink)) {
992 startParsing(xsink, wS, wm);
994 int rc = internParsePending(xsink, code, label, orig_src, offset);
1003 DLLLOCAL
int internParseCommit(
bool standard_parse =
true);
1006 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1012 if (checkParse(xsink)) {
1016 startParsing(xsink, wS, wm);
1019 int rc = internParseCommit();
1022 parseSink =
nullptr;
1030 ProgramRuntimeParseContextHelper pch(xsink, pgm);
1036 internParseRollback(xsink);
1042 printd(5,
"QoreProgram::parse(fp: %p, name: %s, xsink: %p, wS: %p, wm: %d)\n", fp, name, xsink, wS, wm);
1048 printd(5,
"QoreProgram::parse(fp: %p, name: %s) EOF\n", fp, name);
1057 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1062 if (checkParse(xsink)) {
1066 startParsing(xsink, wS, wm);
1070 const char* sname = name;
1073 QoreParseLocationHelper qplh(sname,
nullptr, 0);
1080 beginParsing(sname);
1082 if (!parsing_in_progress) {
1083 parsing_in_progress =
true;
1088 yyset_in(fp, lexer);
1093 internParseCommit();
1096 parseSink =
nullptr;
1102 yylex_destroy(lexer);
1103 if (only_first_except && exceptions_raised > 1)
1104 fprintf(stderr,
"\n%d exception(s) skipped\n\n", exceptions_raised);
1123 if (source && !source->empty() && !src.
set(source,
QCS_DEFAULT, xsink))
1126 parse(tstr->getBuffer(), tlstr->getBuffer(), xsink, wS, wm, source ? src->
getBuffer() : 0, offset);
1129 DLLLOCAL
void parse(
const char* code,
const char* label,
ExceptionSink* xsink,
ExceptionSink* wS,
int wm,
const char* orig_src = 0,
int offset = 0) {
1132 assert(code && code[0]);
1135 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1140 if (checkParse(xsink)) {
1144 startParsing(xsink, wS, wm);
1147 if (!internParsePending(xsink, code, label, orig_src, offset))
1148 internParseCommit();
1151 parseSink =
nullptr;
1160 xsink->
raiseException(
"EXPRESSION-ERROR",
"the expression cannot be empty");
1175 if (source && !source->empty() && !src.
set(source,
QCS_DEFAULT, xsink))
1178 return parseExpression(tstr->c_str(), tlstr->c_str(), xsink, wS, wm, source ? src->
c_str() :
nullptr, offset);
1181 DLLLOCAL q_exp_t parseExpression(
const char* code,
const char* label,
ExceptionSink* xsink,
ExceptionSink* wS,
int wm,
const char* orig_src =
nullptr,
int offset = 0) {
1184 assert(code && code[0]);
1187 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1192 assert(!expression_mode);
1193 assert(!new_expression);
1194 expression_mode =
true;
1196 QoreStringMaker exp_code(
"return (%s);", code);
1198 startParsing(xsink, wS, wm);
1201 if (!internParsePending(xsink, exp_code.c_str(), label, orig_src, offset,
false)) {
1202 internParseCommit(
false);
1204 parsing_in_progress =
false;
1208 parseSink =
nullptr;
1212 expression_mode =
false;
1213 q_exp_t rv = new_expression;
1214 if (new_expression) {
1216 exp_set.erase(new_expression);
1217 delete new_expression;
1220 new_expression =
nullptr;
1226 QORE_TRACE(
"QoreProgram::parseFile()");
1228 printd(5,
"QoreProgram::parseFile(%s)\n", filename);
1231 if (!(fp = fopen(filename,
"r"))) {
1232 if ((only_first_except && !exceptions_raised) || !only_first_except)
1233 xsink->
raiseErrnoException(
"PARSE-EXCEPTION", errno,
"cannot open qore script '%s'", filename);
1234 exceptions_raised++;
1237 ON_BLOCK_EXIT(fclose, fp);
1239 setScriptPath(filename);
1241 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1245 parse(fp, filename, xsink, wS, wm);
1249 assert(!str->
empty());
1263 if (source && !source->empty() && !src.
set(source,
QCS_DEFAULT, xsink))
1266 parsePending(tstr->getBuffer(), tlstr->getBuffer(), xsink, wS, wm, source ? src->
getBuffer() : 0, offset);
1270 DLLLOCAL
void importFunction(
ExceptionSink* xsink, QoreFunction *u,
const qore_ns_private& oldns,
const char* new_name =
nullptr,
bool inject =
false);
1278 thread_local_storage->
set(h);
1286 printd(5,
"QoreProgram::clearThreadData() this: %p h: %p (size: %d)\n",
this, h, h ? h->
size() : 0);
1296 thread_local_storage->
set(
nullptr);
1300 DLLLOCAL
void finalizeThreadData(ThreadProgramData* td,
SafeDerefHelper& sdh) {
1304 thread_local_storage->
set(
nullptr);
1312 pgm_data_map_t::iterator i = pgm_data_map.find(td);
1313 if (i != pgm_data_map.end()) {
1314 i->second->finalize(sdh);
1319 DLLLOCAL
int endThread(ThreadProgramData* td,
ExceptionSink* xsink) {
1320 ThreadLocalProgramData* tlpd =
nullptr;
1329 pgm_data_map_t::iterator i = pgm_data_map.find(td);
1330 if (i == pgm_data_map.end()) {
1334 pgm_data_map.erase(i);
1341 DLLLOCAL
void doTopLevelInstantiation(ThreadLocalProgramData& tlpd) {
1343 const LVList* lvl = sb.getLVList();
1345 for (
unsigned i = 0; i < lvl->size(); ++i) {
1346 lvl->lv[i]->instantiate();
1356 DLLLOCAL
bool setThreadVarData(ThreadProgramData* td, ThreadLocalProgramData*& new_tlpd,
bool run) {
1362 assert(pgm_data_map.find(td) != pgm_data_map.end());
1363 assert(pgm_data_map[td]->inst);
1371 pgm_data_map_t::iterator i = pgm_data_map.find(td);
1372 if (i == pgm_data_map.end()) {
1374 ThreadLocalProgramData* tlpd =
new ThreadLocalProgramData;
1376 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");
1380 pgm_data_map.insert(pgm_data_map_t::value_type(td, tlpd));
1385 printd(5,
"qore_program_private::setThreadVarData() (first) this: %p pgm: %p td: %p\n",
this, pgm, td);
1386 doTopLevelInstantiation(*tlpd);
1392 ThreadLocalProgramData* tlpd = pgm_data_map[td];
1397 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");
1399 if (run && !tlpd->inst) {
1400 doTopLevelInstantiation(*tlpd);
1406 DLLLOCAL
const AbstractQoreZoneInfo*
currentTZ(ThreadProgramData* tpd = get_thread_program_data())
const {
1408 pgm_data_map_t::const_iterator i = pgm_data_map.find(tpd);
1409 if (i != pgm_data_map.end() && i->second->tz_set)
1410 return i->second->tz;
1414 DLLLOCAL
void setTZ(
const AbstractQoreZoneInfo* n_TZ) {
1418 DLLLOCAL
void exportFunction(
ExceptionSink* xsink, qore_program_private* p,
const char* name,
const char* new_name =
nullptr,
bool inject =
false) {
1420 xsink->
raiseException(
"FUNCTION-IMPORT-ERROR",
"cannot import a function from the same Program object");
1425 xsink->
raiseException(
"FUNCTION-IMPORT-ERROR",
"cannot import function \"%s\" in a Program object without PO_ALLOW_INJECTION set", name);
1429 const QoreFunction* u;
1430 const qore_ns_private* ns =
nullptr;
1433 ProgramRuntimeParseAccessHelper rah(xsink, pgm);
1436 u = qore_root_ns_private::runtimeFindFunction(*RootNS, name, ns);
1440 xsink->
raiseException(
"PROGRAM-IMPORTFUNCTION-NO-FUNCTION",
"function '%s' does not exist in the current program scope", name);
1443 p->importFunction(xsink,
const_cast<QoreFunction*
>(u), *ns, new_name, inject);
1447 DLLLOCAL
bool parseExceptionRaised()
const {
1452 DLLLOCAL
void setParseOptionsIntern(
int64 po) {
1453 pwo.parse_options |= po;
1456 DLLLOCAL
void disableParseOptionsIntern(
int64 po) {
1457 pwo.parse_options &= ~po;
1460 DLLLOCAL
void replaceParseOptionsIntern(
int64 po) {
1461 pwo.parse_options = po;
1469 xsink->
raiseException(
"OPTIONS-LOCKED",
"parse options have been locked on this program object");
1473 setParseOptionsIntern(po);
1481 if (((po &
PO_FREE_OPTIONS) != po) && po_locked && !po_allow_restrict) {
1482 xsink->
raiseException(
"OPTIONS-LOCKED",
"parse options have been locked on this program object");
1486 disableParseOptionsIntern(po);
1493 xsink->
raiseException(
"OPTION-ERROR",
"the calling Program does not have the PO_NO_CHILD_PO_RESTRICTIONS option set, and therefore cannot call Program::replaceParseOptions()");
1498 replaceParseOptionsIntern(po);
1502 DLLLOCAL
int parseSetParseOptions(
const QoreProgramLocation* loc,
int64 po) {
1506 parse_error(*loc,
"parse options have been locked on this program object");
1510 setParseOptionsIntern(po);
1514 DLLLOCAL
int parseDisableParseOptions(
const QoreProgramLocation* loc,
int64 po) {
1517 if (((po &
PO_FREE_OPTIONS) != po) && po_locked && !po_allow_restrict) {
1518 parse_error(*loc,
"parse options have been locked on this program object");
1522 disableParseOptionsIntern(po);
1526 DLLLOCAL
void parseSetTimeZone(
const char* zone) {
1530 mergeParseException(xsink);
1534 const AbstractQoreZoneInfo *tz = (*zone ==
'-' || *zone ==
'+') ? QTZM.findCreateOffsetZone(zone, &xsink) : QTZM.findLoadRegion(zone, &xsink);
1537 mergeParseException(xsink);
1541 assert(tz || ((*zone ==
'-' || *zone ==
'+')));
1546 DLLLOCAL
void makeParseException(
const QoreProgramLocation& loc,
const char* err,
QoreStringNode* desc) {
1547 QORE_TRACE(
"QoreProgram::makeParseException()");
1550 if (!requires_exception) {
1551 if ((only_first_except && !exceptions_raised) || !only_first_except) {
1552 QoreException *ne =
new ParseException(loc, err, d.release());
1555 exceptions_raised++;
1559 DLLLOCAL
void parseException(QoreProgramLocation& loc,
const char* fmt, ...) {
1563 if (requires_exception)
1569 va_start(args, fmt);
1570 int rc = desc->
vsprintf(fmt, args);
1575 makeParseException(loc,
"PARSE-EXCEPTION", desc);
1581 dmap_t::iterator i = dmap.find(name);
1582 if (i != dmap.end()) {
1583 i->second.discard(xsink);
1593 DLLLOCAL
const QoreValue getDefine(
const char* name,
bool& is_defined) {
1594 dmap_t::iterator i = dmap.find(name);
1595 if (i != dmap.end()) {
1603 DLLLOCAL
QoreValue runTimeGetDefine(
const char* name,
bool& is_defined) {
1605 return getDefine(name, is_defined).refSelf();
1612 DLLLOCAL
bool unDefine(
const char* name,
ExceptionSink* xsink) {
1613 dmap_t::iterator i = dmap.find(name);
1614 if (i != dmap.end()) {
1615 i->second.discard(xsink);
1622 DLLLOCAL
bool parseUnDefine(
const char* name) {
1623 PreParseHelper pph(
this);
1624 return unDefine(name, parseSink);
1627 DLLLOCAL
bool runTimeUnDefine(
const char* name,
ExceptionSink* xsink) {
1629 return unDefine(name, xsink);
1633 DLLLOCAL
bool isDefined(
const char* name) {
1634 dmap_t::iterator i = dmap.find(name);
1635 return i == dmap.end() ? false :
true;
1638 DLLLOCAL
bool runTimeIsDefined(
const char* name) {
1640 return isDefined(name);
1643 DLLLOCAL
int checkDefine(
const QoreProgramLocation* loc,
const char* str,
ExceptionSink* xsink) {
1644 const char* p = str;
1646 xsink->
raiseException(*loc,
"PARSE-EXCEPTION", 0,
"illegal define variable '%s'; does not begin with an alphabetic character", p);
1651 if (!isalnum(*p) && *p !=
'_') {
1653 xsink->
raiseException(*loc,
"PARSE-EXCEPTION", 0,
"illegal character '%c' in define variable '%s'", *p, str);
1661 DLLLOCAL
void parseDefine(
const QoreProgramLocation* loc,
const char* str,
QoreValue val) {
1662 PreParseHelper pph(
this);
1664 if (checkDefine(loc, str, parseSink))
1667 setDefine(str, val, parseSink);
1671 const QoreProgramLocation* loc = get_runtime_location();
1673 if (checkDefine(loc, str, xsink))
1677 setDefine(str, val, xsink);
1682 ProgramRuntimeParseAccessHelper pah(xsink, pgm);
1685 return qore_root_ns_private::runtimeGetCallReference(*RootNS, name, xsink);
1688 DLLLOCAL
void pushParseOptions(
const char* pf) {
1690 ppo_t::iterator i = ppo.lower_bound(pf);
1691 if (i != ppo.end() && !strcmp(pf, i->first))
1693 ppo.insert(i, ppo_t::value_type(pf, pwo.parse_options));
1697 DLLLOCAL
void restoreParseOptions(
const char* pf) {
1698 ppo_t::iterator i = ppo.find(pf);
1699 if (i != ppo.end()) {
1701 pwo.parse_options = i->second;
1706 DLLLOCAL
void addParseException(
ExceptionSink& xsink,
const QoreProgramLocation* loc) {
1707 if (requires_exception) {
1714 xsink.overrideLocation(*loc);
1730 if ((pos & p_tmp) != pos) {
1731 rv = ((pos & p_tmp) ^ pos);
1736 if (neg && (neg & pwo.parse_options)) {
1737 rv |= (neg & pwo.parse_options);
1745 DLLLOCAL
void exportGlobalVariable(
const char* name,
bool readonly, qore_program_private& tpgm,
ExceptionSink* xsink);
1752 DLLLOCAL
void setThreadTZ(ThreadProgramData* tpd,
const AbstractQoreZoneInfo* tz) {
1754 pgm_data_map_t::iterator i = pgm_data_map.find(tpd);
1755 assert(i != pgm_data_map.end());
1756 i->second->setTZ(tz);
1759 DLLLOCAL
const AbstractQoreZoneInfo* getThreadTZ(ThreadProgramData* tpd,
bool& set)
const {
1761 pgm_data_map_t::const_iterator i = pgm_data_map.find(tpd);
1762 assert(i != pgm_data_map.end());
1763 set = i->second->tz_set;
1764 return i->second->tz;
1767 DLLLOCAL
void clearThreadTZ(ThreadProgramData* tpd) {
1769 pgm_data_map_t::iterator i = pgm_data_map.find(tpd);
1770 assert(i != pgm_data_map.end());
1771 i->second->clearTZ();
1774 DLLLOCAL
void addStatement(AbstractStatement* s);
1777 return parseExpression(source, label, xsink);
1781 ProgramThreadCountContextHelper pch(xsink, pgm,
true);
1785 if (exp_set.find(exp) == exp_set.end()) {
1786 xsink->
raiseException(
"INVALID-EXPRESSION",
"expression not registered to this Program object");
1789 ThreadFrameBoundaryHelper tfbh(
true);
1795 return rv.release();
1798 DLLLOCAL
void deleteExpression(q_exp_t exp) {
1800 q_exp_set_t::iterator i = exp_set.find(exp);
1801 if (i != exp_set.end()) {
1807 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);
1809 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);
1811 DLLLOCAL
const char* addString(
const char* str) {
1812 str_set_t::iterator i = str_set.lower_bound(str);
1813 if (i == str_set.end() || strcmp(*i, str)) {
1814 str_vec.push_back(strdup(str));
1815 i = str_set.insert(i, str_vec.back());
1820 DLLLOCAL
void addFile(
const char*& file) {
1821 file = addString(file);
1822 printd(5,
"qore_program_private::addFile('%s')\n", file);
1823 addStatementToIndexIntern(&statementByFileIndex, file,
nullptr, -1,
nullptr, -1);
1826 DLLLOCAL
void addFile(
const char*& file,
const char*& source,
int offset) {
1827 file = addString(file);
1829 source = addString(source);
1831 printd(5,
"qore_program_private::addFile('%s', '%s', %d)\n", file, source ? source :
"(null)", offset);
1832 addStatementToIndexIntern(&statementByFileIndex, file,
nullptr, -1, source, offset);
1834 addStatementToIndexIntern(&statementByLabelIndex, source,
nullptr, -1, file, offset);
1838 DLLLOCAL
void addUserFeature(
const char* f) {
1840 assert(!userFeatureList.find(f));
1841 userFeatureList.push_back(f);
1844 DLLLOCAL
void removeUserFeature(
const char* f) {
1845 CharPtrList::iterator i = userFeatureList.safe_dslist<std::string>::find(f);
1846 assert(i != userFeatureList.end());
1847 userFeatureList.erase(i);
1850 DLLLOCAL
void addFeature(
const char* f) {
1851 assert(!featureList.find(f));
1852 featureList.push_back(f);
1855 DLLLOCAL
void removeFeature(
const char* f) {
1856 CharPtrList::iterator i = featureList.safe_dslist<std::string>::find(f);
1857 assert(i != featureList.end());
1858 featureList.erase(i);
1861 DLLLOCAL
void runtimeImportSystemClassesIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1862 DLLLOCAL
void runtimeImportSystemConstantsIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1863 DLLLOCAL
void runtimeImportSystemFunctionsIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1864 DLLLOCAL
void runtimeImportSystemHashDeclsIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1866 DLLLOCAL
void runtimeImportSystemClasses(
ExceptionSink* xsink);
1867 DLLLOCAL
void runtimeImportSystemConstants(
ExceptionSink* xsink);
1868 DLLLOCAL
void runtimeImportSystemFunctions(
ExceptionSink* xsink);
1869 DLLLOCAL
void runtimeImportSystemHashDecls(
ExceptionSink* xsink);
1878 assert(extmap.find(owner) == extmap.end());
1879 extmap.insert(extmap_t::value_type(owner, pud));
1884 extmap_t::const_iterator i = extmap.find(owner);
1885 return i == extmap.end() ? nullptr : i->second;
1890 extmap_t::iterator i = extmap.find(owner);
1891 if (i == extmap.end()) {
1900 return qore_root_ns_private::getGlobalVars(*RootNS);
1903 DLLLOCAL LocalVar* createLocalVar(
const char* name,
const QoreTypeInfo* typeInfo);
1905 DLLLOCAL
const AbstractQoreFunctionVariant* runtimeFindCall(
const char* name,
const QoreListNode* params,
ExceptionSink* xsink);
1910 return pgm.priv->runtimeFindClass(class_name, xsink);
1914 pgm.priv->doThreadInit(xsink);
1919 if (!pgm.priv->exec_class) {
1920 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>))");
1923 pgm.priv->exec_class_rv.discard(xsink);
1924 pgm.priv->exec_class_rv = rv.release();
1930 return pgm.priv->preregisterNewThread(xsink);
1934 DLLLOCAL
static void cancelPreregistration(
QoreProgram& pgm) {
1935 pgm.priv->cancelPreregistration();
1939 DLLLOCAL
static void registerNewThread(
QoreProgram& pgm,
int tid) {
1940 pgm.priv->registerNewThread(tid);
1944 pgm.priv->runtimeImportSystemClasses(xsink);
1948 pgm.priv->runtimeImportSystemHashDecls(xsink);
1952 pgm.priv->runtimeImportSystemConstants(xsink);
1956 pgm.priv->runtimeImportSystemFunctions(xsink);
1960 pgm.priv->runtimeImportSystemApi(xsink);
1963 DLLLOCAL
static qore_program_private* get(
QoreProgram& pgm) {
1968 pgm.priv->clearThreadData(xsink);
1971 DLLLOCAL
static void addUserFeature(
QoreProgram& pgm,
const char* f) {
1972 pgm.priv->addUserFeature(f);
1975 DLLLOCAL
static void addStatement(
QoreProgram& pgm, AbstractStatement* s) {
1976 pgm.priv->addStatement(s);
1979 DLLLOCAL
static const AbstractQoreZoneInfo* currentTZIntern(
QoreProgram& pgm) {
1980 return pgm.priv->TZ;
1984 return pgm.priv->lockParsing(xsink);
1987 DLLLOCAL
static void unlockParsing(
QoreProgram& pgm) {
1988 pgm.priv->unlockParsing();
1992 return pgm.priv->incThreadCount(xsink);
1995 DLLLOCAL
static void decThreadCount(
QoreProgram& pgm,
int tid) {
1996 pgm.priv->decThreadCount(tid);
2000 DLLLOCAL
static void addSignal(
QoreProgram& pgm,
int sig) {
2001 assert(pgm.priv->sigset.find(sig) == pgm.priv->sigset.end());
2002 pgm.priv->sigset.insert(sig);
2006 DLLLOCAL
static void delSignal(
QoreProgram& pgm,
int sig) {
2007 assert(pgm.priv->sigset.find(sig) != pgm.priv->sigset.end());
2008 pgm.priv->sigset.erase(sig);
2012 pgm.priv->qore_program_private_base::startThread(xsink);
2016 return pgm.priv->setThreadInit(n_thr_init, xsink);
2020 return pgm->priv->runtimeGetCallReference(name, xsink);
2023 DLLLOCAL
static const ParseWarnOptions& getParseWarnOptions(
const QoreProgram* pgm) {
2024 return pgm->priv->pwo;
2027 DLLLOCAL
static bool setSaveParseWarnOptions(
const QoreProgram* pgm,
const ParseWarnOptions &new_opts, ParseWarnOptions &old_opts) {
2028 if (new_opts == pgm->priv->pwo)
2030 old_opts = pgm->priv->pwo;
2031 pgm->priv->pwo = new_opts;
2035 DLLLOCAL
static void setParseWarnOptions(
const QoreProgram* pgm,
const ParseWarnOptions &new_opts) {
2036 pgm->priv->pwo = new_opts;
2039 DLLLOCAL
static bool setThreadVarData(
QoreProgram* pgm, ThreadProgramData* td, ThreadLocalProgramData* &tlpd,
bool run) {
2040 return pgm->priv->setThreadVarData(td, tlpd, run);
2044 pgm->priv->makeParseException(loc,
"PARSE-EXCEPTION", desc);
2047 DLLLOCAL
static void makeParseException(
QoreProgram* pgm,
const QoreProgramLocation &loc,
const char* err,
QoreStringNode* desc) {
2048 pgm->priv->makeParseException(loc, err, desc);
2053 return pgm->priv->getDefine(name, is_defined);
2056 DLLLOCAL
static const QoreValue parseGetDefine(
QoreProgram* pgm,
const char* name,
bool& is_defined) {
2057 return pgm->priv->getDefine(name, is_defined);
2062 return pgm->priv->runTimeGetDefine(name, is_defined);
2065 DLLLOCAL
static QoreValue runTimeGetDefine(
QoreProgram* pgm,
const char* name,
bool& is_defined) {
2066 return pgm->priv->runTimeGetDefine(name, is_defined);
2070 return pgm->priv->runTimeGetAllDefines();
2073 DLLLOCAL
static bool parseUnDefine(
QoreProgram* pgm,
const char* name) {
2074 return pgm->priv->parseUnDefine(name);
2078 return pgm->priv->runTimeUnDefine(name, xsink);
2081 DLLLOCAL
static bool parseIsDefined(
QoreProgram* pgm,
const char* name) {
2082 return pgm->priv->isDefined(name);
2085 DLLLOCAL
static bool runTimeIsDefined(
QoreProgram* pgm,
const char* name) {
2086 return pgm->priv->runTimeIsDefined(name);
2089 DLLLOCAL
static void parseDefine(
QoreProgram* pgm,
const QoreProgramLocation* loc,
const char* str,
QoreValue val) {
2090 pgm->priv->parseDefine(loc, str, val);
2094 pgm->priv->runTimeDefine(str, val, xsink);
2097 DLLLOCAL
static void addParseException(
QoreProgram* pgm,
ExceptionSink* xsink,
const QoreProgramLocation* loc =
nullptr) {
2099 pgm->priv->addParseException(*xsink, loc);
2103 DLLLOCAL
static void addParseException(
QoreProgram* pgm,
ExceptionSink& xsink,
const QoreProgramLocation* loc =
nullptr) {
2104 pgm->priv->addParseException(xsink, loc);
2107 DLLLOCAL
static void exportFunction(
QoreProgram* srcpgm,
ExceptionSink* xsink,
QoreProgram* trgpgm,
const char* name,
const char* new_name =
nullptr,
bool inject =
false) {
2108 srcpgm->priv->exportFunction(xsink, trgpgm->priv, name, new_name, inject);
2112 return pgm->priv->parseAddDomain(n_dom);
2116 return pgm.priv->dom;
2120 pgm.priv->dom |= n_dom;
2124 int64 rv = pgm.priv->pwo.parse_options;
2125 pgm.priv->pwo.parse_options = po;
2129 DLLLOCAL
static void makeParseWarning(
QoreProgram* pgm,
const QoreProgramLocation &loc,
int code,
const char* warn,
const char* fmt, ...) {
2131 if (!pgm->priv->warnSink || !(code & pgm->priv->pwo.warn_mask))
2137 va_start(args, fmt);
2138 int rc = desc->
vsprintf(fmt, args);
2143 QoreException *ne =
new ParseException(loc, warn, desc);
2144 pgm->priv->warnSink->raiseException(ne);
2147 DLLLOCAL
static void makeParseWarning(
QoreProgram* pgm,
const QoreProgramLocation &loc,
int code,
const char* warn,
QoreStringNode* desc) {
2149 if (!pgm->priv->warnSink || !(code & pgm->priv->pwo.warn_mask)) {
2154 QoreException *ne =
new ParseException(loc, warn, desc);
2155 pgm->priv->warnSink->raiseException(ne);
2159 pgm->priv->exportGlobalVariable(name, readonly, *(tpgm->priv), xsink);
2162 DLLLOCAL
void attachDebug(
const qore_debug_program_private* n_dpgm) {
2163 printd(5,
"qore_program_private::attachDebug(n_dpgm: %p), dpgm: %p\n", n_dpgm, dpgm);
2169 dpgm =
const_cast<qore_debug_program_private*
>(n_dpgm);
2170 printd(5,
"qore_program_private::attachDebug, dpgm: %p, pgm_data_map: size:%d, begin: %p, end: %p\n", dpgm, pgm_data_map.size(), pgm_data_map.begin(), pgm_data_map.end());
2171 for (
auto& i : pgm_data_map) {
2172 i.second->dbgPendingAttach();
2173 i.second->dbgBreak();
2177 DLLLOCAL
void detachDebug(
const qore_debug_program_private* n_dpgm) {
2178 printd(5,
"qore_program_private::detachDebug(n_dpgm: %p), dpgm: %p\n", n_dpgm, dpgm);
2181 assert(n_dpgm==dpgm);
2185 printd(5,
"qore_program_private::detachDebug, dpgm: %p, pgm_data_map: size:%d, begin: %p, end: %p\n", dpgm, pgm_data_map.size(), pgm_data_map.begin(), pgm_data_map.end());
2186 for (
auto& i : pgm_data_map) {
2187 i.second->dbgPendingDetach();
2192 DLLLOCAL
void onAttach(DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2193 DLLLOCAL
void onDetach(DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2194 DLLLOCAL
void onStep(
const StatementBlock *blockStatement,
const AbstractStatement *statement,
unsigned bkptId,
int &flow, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2195 DLLLOCAL
void onFunctionEnter(
const StatementBlock *statement, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2196 DLLLOCAL
void onFunctionExit(
const StatementBlock *statement,
QoreValue& returnValue, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2197 DLLLOCAL
void onException(
const AbstractStatement *statement, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2198 DLLLOCAL
void onExit(
const StatementBlock *statement,
QoreValue& returnValue, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2200 DLLLOCAL
int breakProgramThread(
int tid) {
2201 printd(5,
"qore_program_private::breakProgramThread(), this: %p, tid: %d\n",
this,
q_gettid());
2203 for (
auto& i : pgm_data_map) {
2204 if (i.first->gettid() == tid) {
2205 i.second->dbgBreak();
2212 DLLLOCAL
void breakProgram() {
2213 printd(5,
"qore_program_private::breakProgram(), this: %p\n",
this);
2215 for (
auto& i : pgm_data_map) {
2216 i.second->dbgBreak();
2221 if (!bkpt ||
this == bkpt->pgm)
return;
2222 if (!checkAllowDebugging(xsink))
2228 breakpointList.push_back(bkpt);
2233 DLLLOCAL
void deleteAllBreakpoints() {
2235 for (QoreBreakpointList_t::iterator it = breakpointList.begin(); it != breakpointList.end(); ++it) {
2236 (*it)->unassignAllStatements();
2237 (*it)->pgm =
nullptr;
2240 breakpointList.clear();
2243 DLLLOCAL
void getBreakpoints(QoreBreakpointList_t &bkptList) {
2246 for (QoreBreakpointList_t::iterator it = breakpointList.begin(); it != breakpointList.end(); ++it) {
2247 bkptList.push_back(*it);
2252 DLLLOCAL
void getStatementBreakpoints(
const AbstractStatement* statement, QoreBreakpointList_t &bkptList) {
2255 if (statement->breakpoints) {
2256 for (std::list<QoreBreakpoint*>::iterator it = statement->breakpoints->begin(); it != statement->breakpoints->end(); ++it) {
2257 bkptList.push_back(*it);
2263 DLLLOCAL
inline unsigned onCheckBreakpoint(
const AbstractStatement *statement,
ExceptionSink* xsink) {
2273 DLLLOCAL
unsigned long getStatementId(
const AbstractStatement* statement)
const {
2277 ReverseStatementIdMap_t::const_iterator i = reverseStatementIds.find((AbstractStatement*) statement);
2278 if (i == reverseStatementIds.end())
2285 if (statementId == 0 || statementId > statementIds.size())
2287 return statementIds[statementId-1];
2290 DLLLOCAL
unsigned getProgramId()
const {
2303 qore_root_ns_private::clearData(*RootNS, xsink);
2306 DLLLOCAL
static QoreProgram* resolveProgramId(
unsigned programId) {
2307 printd(5,
"qore_program_private::resolveProgramId(%x)\n", programId);
2309 for (qore_program_to_object_map_t::iterator i = qore_program_to_object_map.begin(); i != qore_program_to_object_map.end(); i++) {
2310 if (i->first->priv->programId == programId)
2319 xsink->
raiseException(
"DEBUGGING",
"program does not provide internal data for debugging");
2327 DLLLOCAL
void addStatementToIndexIntern(name_section_sline_statement_map_t* statementIndex,
const char* key, AbstractStatement *statement,
int offs,
const char* section,
int sectionOffs);
2328 DLLLOCAL
static void registerStatement(
QoreProgram *pgm, AbstractStatement *statement,
bool addToIndex);
2329 DLLLOCAL
QoreHashNode* getSourceIndicesIntern(name_section_sline_statement_map_t* statementIndex,
ExceptionSink* xsink)
const;
2331 return getSourceIndicesIntern(&statementByLabelIndex, xsink);
2334 return getSourceIndicesIntern(&statementByFileIndex, xsink);
2337 DLLLOCAL AbstractStatement* getStatementFromIndex(
const char* name,
int line) {
2338 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d), this: %p, file#: %d, label#: %d\n", name, line,
this, statementByFileIndex.size(), statementByLabelIndex.size());
2340 name_section_sline_statement_map_t::iterator it;
2341 if (statementByFileIndex.empty()) {
2344 bool addOffs =
true;
2345 if (!name || *name ==
'\0') {
2346 if (statementByFileIndex.size() != 1)
2348 it = statementByFileIndex.begin();
2350 size_t l = strlen(name);
2351 it = statementByFileIndex.find(name);
2352 if (it == statementByFileIndex.end()) {
2353 it = statementByLabelIndex.find(name);
2354 if (it == statementByLabelIndex.end()) {
2357 it = statementByFileIndex.begin();
2358 while (it != statementByFileIndex.end()) {
2359 size_t k = strlen(it->first);
2361 if (strcmp(name, it->first + k - l) == 0) {
2363 if (k == l || name[0] ==
'/' || it->first[k-l-1] ==
'/') {
2370 if (it == statementByFileIndex.end()) {
2371 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) no suffix match, this: %p\n", name, line,
this);
2374 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found by file suffix match, this: %p\n", name, line,
this);
2377 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found by label full match, this: %p\n", name, line,
this);
2380 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found by file full match, this: %p\n", name, line,
this);
2383 sline_statement_map_t *ssm = &it->second->statementMap;
2384 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found '%s', this: %p, ssm#: %d\n", name, line, it->first,
this, ssm->size());
2385 if (ssm->size() == 0)
2388 sline_statement_map_t::iterator li = ssm->upper_bound(line);
2389 if (li == ssm->begin()) {
2390 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) no statement found by line #1, this: %p\n", name, line,
this);
2396 AbstractStatement* st =
nullptr;
2399 if (ln != li->first) {
2403 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) {
2404 int n = li->second->loc->end_line - li->second->loc->start_line;
2417 if (li == ssm->begin())
2422 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);
2424 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) no statement found by line #2, this: %p\n", name, line,
this);
2430 printd(5,
"qore_program_private::registerQoreObject() pgm: %p, pgmid: %d\n", pgm, getProgramId());
2432 qore_program_to_object_map_t::iterator i = qore_program_private::qore_program_to_object_map.find(pgm);
2433 assert(i != qore_program_private::qore_program_to_object_map.end());
2434 if (i->second && i->second != o) {
2435 xsink->
raiseException(
"PROGRAM-ERROR",
"The Program has already assigned QoreObject");
2442 printd(5,
"qore_program_private::unregisterQoreObject() pgm: %p, pgmid: %d\n", pgm, getProgramId());
2444 qore_program_to_object_map_t::iterator i = qore_program_private::qore_program_to_object_map.find(pgm);
2445 assert(i != qore_program_private::qore_program_to_object_map.end());
2446 assert(i->second == o);
2447 i->second =
nullptr;
2452 qore_program_to_object_map_t::iterator i = qore_program_to_object_map.find(pgm);
2453 if (i == qore_program_to_object_map.end()) {
2462 qore_program_to_object_map_t::iterator i = qore_program_to_object_map.find(pgm);
2463 assert(i != qore_program_to_object_map.end());
2465 printd(5,
"qore_program_private::getQoreObject() pgm: %p, pgmid: %d, second: %p\n", i->first, i->first->getProgramId(), i->second);
2469 printd(5,
"qore_program_private::getQoreObject() pgm: %p, pgmid: %d, new second: %p\n", pgm, pgm->
getProgramId(), i->second);
2479 qore_program_to_object_map_t::iterator i = qore_program_to_object_map.begin();
2480 while (i != qore_program_to_object_map.end()) {
2482 printd(5,
"qore_program_private::getAllQoreObjects() pgm: %p, pgmid: %d, second: %p\n", i->first, i->first->getProgramId(), i->second);
2486 printd(5,
"qore_program_private::getAllQoreObjects() pgm: %p, pgmid: %d, new second: %p\n", i->first, i->first->getProgramId(), i->second);
2489 (*l)->push(i->second,
nullptr);
2496 class ParseWarnHelper :
public ParseWarnOptions {
2500 DLLLOCAL ParseWarnHelper(
const ParseWarnOptions &new_opts) {
2502 restore = pgm ? qore_program_private::setSaveParseWarnOptions(pgm, new_opts, *
this) : false;
2504 DLLLOCAL ~ParseWarnHelper() {
2506 qore_program_private::setParseWarnOptions(
getProgram(), *
this);
2510 typedef std::map<QoreProgram*, qore_program_private*> qore_program_map_t;
2513 class qore_debug_program_private {
2518 qore_program_map_t qore_program_map;
2521 DLLLOCAL qore_debug_program_private(
QoreDebugProgram *n_dpgm): dpgm(n_dpgm) {};
2522 DLLLOCAL ~qore_debug_program_private() {
2523 assert(qore_program_map.empty());
2527 if (!pgm->priv->checkAllowDebugging(xsink))
2530 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2531 printd(5,
"qore_debug_program_private::addProgram(), this: %p, pgm: %p, i: %p, end: %p\n",
this, pgm, i, qore_program_map.end());
2532 if (i != qore_program_map.end())
2534 qore_program_map.insert(qore_program_map_t::value_type(pgm, pgm->priv));
2536 pgm->priv->attachDebug(
this);
2541 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2542 printd(5,
"qore_debug_program_private::removeProgram(), this: %p, pgm: %p, i: %p, end: %p\n",
this, pgm, i, qore_program_map.end());
2543 if (i == qore_program_map.end())
2545 pgm->priv->detachDebug(
this);
2546 qore_program_map.erase(i);
2551 DLLLOCAL
void removeAllPrograms() {
2553 printd(5,
"qore_debug_program_private::removeAllPrograms(), this: %p\n",
this);
2554 qore_program_map_t::iterator i;
2555 while ((i = qore_program_map.begin()) != qore_program_map.end()) {
2556 qore_program_private* qpp = i->second;
2558 qore_program_map.erase(i);
2559 qpp->detachDebug(
this);
2566 printd(5,
"qore_debug_program_private::getAllProgramObjects(), this: %p\n",
this);
2568 qore_program_map_t::iterator i = qore_program_map.begin();
2569 while (i != qore_program_map.end()) {
2572 (*l)->push(o,
nullptr);
2579 DLLLOCAL
void onAttach(
QoreProgram *pgm, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2580 AutoQoreCounterDec ad(&debug_program_counter);
2581 dpgm->onAttach(pgm, rs, rts, xsink);
2583 DLLLOCAL
void onDetach(
QoreProgram *pgm, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2584 AutoQoreCounterDec ad(&debug_program_counter);
2585 dpgm->onDetach(pgm, rs, rts, xsink);
2593 DLLLOCAL
void onStep(
QoreProgram *pgm,
const StatementBlock *blockStatement,
const AbstractStatement *statement,
unsigned bkptId,
int &flow, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2594 AutoQoreCounterDec ad(&debug_program_counter);
2595 dpgm->
onStep(pgm, blockStatement, statement, bkptId, flow, rs, rts, xsink);
2598 DLLLOCAL
void onFunctionEnter(
QoreProgram *pgm,
const StatementBlock *statement, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2599 AutoQoreCounterDec ad(&debug_program_counter);
2605 DLLLOCAL
void onFunctionExit(
QoreProgram *pgm,
const StatementBlock *statement,
QoreValue& returnValue, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2606 AutoQoreCounterDec ad(&debug_program_counter);
2607 dpgm->
onFunctionExit(pgm, statement, returnValue, rs, rts, xsink);
2612 DLLLOCAL
void onException(
QoreProgram* pgm,
const AbstractStatement* statement, DebugRunStateEnum& rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2613 AutoQoreCounterDec ad(&debug_program_counter);
2614 dpgm->
onException(pgm, statement, rs, rts, xsink);
2619 DLLLOCAL
void onExit(
QoreProgram *pgm,
const StatementBlock *statement,
QoreValue& returnValue, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2620 AutoQoreCounterDec ad(&debug_program_counter);
2621 dpgm->
onExit(pgm, statement, returnValue, rs, rts, xsink);
2624 DLLLOCAL
int breakProgramThread(
QoreProgram* pgm,
int tid) {
2631 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2632 printd(5,
"qore_debug_program_private::breakProgramThread(), this: %p, pgm: %p, i: %p, end: %p, tid: %d\n",
this, pgm, i, qore_program_map.end(), tid);
2633 if (i == qore_program_map.end())
2635 if (i->second->breakProgramThread(tid))
2647 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2648 printd(5,
"qore_debug_program_private::breakProgram(), this: %p, pgm: %p, i: %p, end: %p\n",
this, pgm, i, qore_program_map.end());
2649 if (i == qore_program_map.end())
2651 i->second->breakProgram();
2655 DLLLOCAL
void waitForTerminationAndClear(
ExceptionSink* xsink) {
2656 removeAllPrograms();
2661 DLLLOCAL
int getInterruptedCount() {
2662 return debug_program_counter.
getCount();