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/QoreDebugProgram.h" 47 #include "qore/QoreRWLock.h" 48 #include "qore/vector_map" 49 #include "qore/vector_set" 56 typedef vector_map_t<int, unsigned> ptid_map_t;
59 typedef std::vector<AbstractStatement*> stmt_vec_t;
61 class QoreParseLocationHelper {
63 DLLLOCAL QoreParseLocationHelper(
const char* file,
const char* src,
int offset) {
64 thread_set_class_and_ns(
nullptr,
nullptr, cls, ns);
65 beginParsing(file,
nullptr, src, offset);
68 DLLLOCAL ~QoreParseLocationHelper() {
70 thread_set_class_and_ns(cls, ns);
75 const qore_class_private* cls;
79 class CharPtrList :
public safe_dslist<std::string> {
83 DLLLOCAL
bool find(
const char* str)
const {
84 const_iterator i = begin();
96 typedef safe_dslist<LocalVar*> local_var_list_t;
98 class LocalVariableList :
public local_var_list_t {
100 DLLLOCAL LocalVariableList() {
103 DLLLOCAL ~LocalVariableList() {
104 for (local_var_list_t::iterator i = begin(), e = end(); i != e; ++i) {
112 #include "qore/intern/ThreadLocalVariableData.h" 113 #include "qore/intern/ThreadClosureVariableStack.h" 115 hashdecl ThreadLocalProgramData {
118 DLLLOCAL ThreadLocalProgramData(
const ThreadLocalProgramData& old) =
delete;
121 DebugRunStateEnum runState;
123 const AbstractStatement* runToStatement;
125 int functionCallLevel;
127 inline void setRunState(DebugRunStateEnum rs,
const AbstractStatement* rts) {
128 assert(rs < DBG_RS_STOPPED);
129 if (rs == DBG_RS_UNTIL_RETURN) {
130 functionCallLevel = 1;
132 printd(5,
"ThreadLocalProgramData::setRunState(), this: %p, rs: %d->%d, rts: %p\n",
this, runState, rs, rts);
134 runToStatement = rts;
137 volatile bool breakFlag;
139 inline void checkBreakFlag() {
140 if (breakFlag && runState != DBG_RS_DETACH) {
142 if (runState != DBG_RS_STOPPED) {
143 runState = DBG_RS_STEP;
145 printd(5,
"ThreadLocalProgramData::checkBreakFlag(), this: %p, rs: %d\n",
this, runState);
151 if (runState != DBG_RS_STOPPED) {
152 if (attachFlag > 0) {
157 }
else if (attachFlag < 0) {
166 ThreadLocalVariableData lvstack;
168 ThreadClosureVariableStack cvstack;
170 const AbstractQoreZoneInfo* tz =
nullptr;
177 DLLLOCAL ThreadLocalProgramData() : runState(DBG_RS_DETACH), functionCallLevel(0), breakFlag(false), tz(0), tz_set(false), inst(false) {
178 printd(5,
"ThreadLocalProgramData::ThreadLocalProgramData() this: %p\n",
this);
181 DLLLOCAL ~ThreadLocalProgramData() {
182 printd(5,
"ThreadLocalProgramData::~ThreadLocalProgramData() this: %p, rs: %d\n",
this, runState);
183 assert(lvstack.empty());
184 assert(cvstack.empty());
188 lvstack.finalize(cl);
189 cvstack.finalize(cl);
198 DLLLOCAL
void setTZ(
const AbstractQoreZoneInfo* n_tz) {
203 DLLLOCAL
void clearTZ() {
241 DLLLOCAL
int dbgStep(
const StatementBlock* blockStatement,
const AbstractStatement* statement,
ExceptionSink* xsink);
245 DLLLOCAL
void dbgFunctionEnter(
const StatementBlock* statement,
ExceptionSink* xsink);
249 DLLLOCAL
void dbgFunctionExit(
const StatementBlock* statement,
QoreValue& returnValue,
ExceptionSink* xsink);
253 DLLLOCAL
void dbgException(
const AbstractStatement* statement,
ExceptionSink* xsink);
262 DLLLOCAL
void dbgBreak() {
263 printd(5,
"ThreadLocalProgramData::dbgBreak(), this: %p\n",
this);
269 DLLLOCAL
void dbgPendingAttach() {
270 printd(5,
"ThreadLocalProgramData::dbgPendingAttach(), this: %p\n",
this);
276 DLLLOCAL
void dbgPendingDetach() {
277 printd(5,
"ThreadLocalProgramData::dbgPendingDetach(), this: %p\n",
this);
284 DLLLOCAL
bool dbgIsAttached() {
285 return runState != DBG_RS_DETACH;
290 typedef vector_map_t<ThreadProgramData*, ThreadLocalProgramData*> pgm_data_map_t;
294 typedef vector_map_t<std::string, QoreValue> dmap_t;
298 typedef vector_map_t<const char*, int64> ppo_t;
301 class AbstractQoreZoneInfo;
305 DLLLOCAL
bool operator()(
const QoreProgramLocation* p1,
const QoreProgramLocation* p2)
const {
313 hashdecl pgmloc_vec_t :
public std::vector<QoreProgramLocation*> {
314 DLLLOCAL ~pgmloc_vec_t() {
318 DLLLOCAL
void clear() {
319 for (
auto& i : *
this) {
323 std::vector<QoreProgramLocation*>::clear();
327 class qore_program_private_base {
328 friend class QoreProgramAccessHelper;
331 DLLLOCAL
void setDefines();
333 typedef vector_map_t<const char*, AbstractQoreProgramExternalData*> extmap_t;
338 LocalVariableList local_var_list;
343 unsigned thread_count;
344 unsigned thread_waiting;
345 unsigned parse_count;
354 typedef std::set<const char*, ltstr> str_set_t;
358 typedef std::set<const QoreProgramLocation*, ltpgm> loc_set_t;
362 CharPtrList featureList;
364 CharPtrList userFeatureList;
379 TopLevelStatementBlock sb;
382 bool only_first_except : 1,
384 po_allow_restrict : 1,
387 requires_exception : 1,
389 parsing_in_progress : 1,
396 int exceptions_raised,
399 ParseWarnOptions pwo;
404 std::string exec_class_name, script_dir, script_path, script_name, include_path;
407 qpgm_thread_local_storage_t* thread_local_storage;
411 mutable unsigned twaiting;
414 pgm_data_map_t pgm_data_map;
417 const AbstractQoreZoneInfo* TZ;
435 : thread_count(0), thread_waiting(0), parse_count(0), plock(&ma_recursive), parseSink(nullptr), warnSink(nullptr), pendingParseSink(nullptr), RootNS(nullptr), QoreNS(nullptr),
437 only_first_except(false), po_locked(false), po_allow_restrict(true), exec_class(false), base_object(false),
438 requires_exception(false),
440 parsing_in_progress(false),
444 exceptions_raised(0), ptid(0), pwo(n_parse_options), dom(0), pend_dom(0), thread_local_storage(nullptr), twaiting(0),
445 thr_init(nullptr), pgm(n_pgm) {
446 printd(QPP_DBG_LVL,
"qore_program_private_base::qore_program_private_base() this: %p pgm: %p po: " QLLD
"\n",
this, pgm, n_parse_options);
449 pgm->priv = (qore_program_private*)
this;
452 setParent(p_pgm, n_parse_options);
454 TZ = QTZM.getLocalZoneInfo();
459 Var *var = qore_root_ns_private::runtimeCreateVar(*RootNS, *QoreNS,
"ARGV", listTypeInfo,
true);
461 var->setInitial(ARGV->
copy());
463 var = qore_root_ns_private::runtimeCreateVar(*RootNS, *QoreNS,
"QORE_ARGV", listTypeInfo,
true);
464 if (var && QORE_ARGV)
465 var->setInitial(QORE_ARGV->
copy());
467 var = qore_root_ns_private::runtimeCreateVar(*RootNS, *QoreNS,
"ENV", hashTypeInfo,
true);
469 var->setInitial(ENV->
copy());
474 DLLLOCAL ~qore_program_private_base() {
475 printd(QPP_DBG_LVL,
"qore_program_private_base::~qore_program_private_base() this: %p pgm: %p\n",
this, pgm);
479 DLLLOCAL
const QoreProgramLocation* getLocation(
int sline,
int eline);
480 DLLLOCAL
const QoreProgramLocation* getLocation(
const QoreProgramLocation&,
int sline,
int eline);
488 DLLLOCAL
void newProgram();
491 class PreParseHelper {
493 qore_program_private_base *p;
497 DLLLOCAL PreParseHelper(qore_program_private_base *n_p) : p(n_p), swapped(false) {
499 if (!p->pendingParseSink)
501 p->parseSink = p->pendingParseSink;
506 DLLLOCAL ~PreParseHelper() {
508 p->parseSink =
nullptr;
512 class qore_debug_program_private;
514 class AutoQoreCounterDec {
518 AutoQoreCounterDec() {}
520 AutoQoreCounterDec(
QoreCounter* n_cnt,
bool incNow =
true): cnt(n_cnt), incFlag(false) {
525 ~AutoQoreCounterDec() {
537 class qore_program_private :
public qore_program_private_base {
540 DLLLOCAL
void init(
QoreProgram* n_pgm,
int64 n_parse_options,
const AbstractQoreZoneInfo *n_TZ = QTZM.getLocalZoneInfo()) {
548 if (!pendingParseSink)
554 qore_debug_program_private* dpgm;
556 QoreBreakpointList_t breakpointList;
559 typedef std::map<int, AbstractStatement*> sline_statement_map_t;
561 typedef std::map<const char*, int, ltstr> section_offset_map_t;
563 hashdecl section_sline_statement_map {
564 section_offset_map_t sectionMap;
565 sline_statement_map_t statementMap;
568 typedef section_sline_statement_map section_sline_statement_map_t;
571 typedef vector_map_t<const char*, section_sline_statement_map_t*> name_section_sline_statement_map_t;
575 name_section_sline_statement_map_t statementByFileIndex;
576 name_section_sline_statement_map_t statementByLabelIndex;
579 typedef std::vector<AbstractStatement*> StatementVector_t;
580 StatementVector_t statementIds;
583 typedef std::map<AbstractStatement*, unsigned long> ReverseStatementIdMap_t;
584 ReverseStatementIdMap_t reverseStatementIds;
591 DLLLOCAL qore_debug_program_private* getDebugProgram(AutoQoreCounterDec& ad) {
594 qore_debug_program_private* ret = dpgm;
603 DLLLOCAL
bool isBreakpointRegistered(
const QoreBreakpoint *bkpt)
const {
604 return std::find(breakpointList.begin(), breakpointList.end(), bkpt) != breakpointList.end();
608 typedef std::map<QoreProgram*, QoreObject*> qore_program_to_object_map_t;
609 static qore_program_to_object_map_t qore_program_to_object_map;
611 static volatile unsigned programIdCounter;
617 DLLLOCAL ~qore_program_private();
619 DLLLOCAL
void depRef() {
624 DLLLOCAL
void depDeref() {
641 for (pgm_data_map_t::iterator i = pgm_data_map.begin(), e = pgm_data_map.end(); i != e; ++i)
642 i->second->finalize(cl);
647 for (arg_vec_t::iterator i = cl->begin(), e = cl->end(); i != e; ++i) {
655 for (pgm_data_map_t::iterator i = pgm_data_map.begin(), e = pgm_data_map.end(); i != e; ++i) {
656 i->second->del(xsink);
657 i->first->delProgram(pgm);
661 DLLLOCAL
void waitForTerminationAndClear(
ExceptionSink* xsink);
673 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed has already been deleted and therefore no new threads can be started in it");
682 DLLLOCAL
void cancelPreregistration() {
686 assert(thread_count > 0);
687 if (!--thread_count && thread_waiting)
692 DLLLOCAL
void registerNewThread(
int tid) {
696 assert(thread_count);
717 if (ptid && ptid != tid) {
718 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed has already been deleted and therefore cannot be accessed at runtime");
721 if (parsing_in_progress) {
722 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed is currently undergoing parsing and cannot be accessed at runtime");
731 DLLLOCAL
void incThreadCount() {
737 if (ptid && ptid != tid) {
738 throw QoreStandardException(
"PROGRAM-ERROR",
"the Program accessed has already been deleted and therefore cannot be accessed at runtime");
740 if (parsing_in_progress) {
741 throw QoreStandardException(
"PROGRAM-ERROR",
"the Program accessed is currently undergoing parsing and cannot be accessed at runtime");
748 DLLLOCAL
void decThreadCount(
int tid) {
752 ptid_map_t::iterator i = tidmap.find(tid);
753 assert(i != tidmap.end());
757 assert(thread_count > 0);
758 if (!--thread_count && thread_waiting)
767 for (
auto& i : tidmap) {
768 l.
push(i.first,
nullptr);
778 while (parse_count) {
785 if (ptid && ptid !=
gettid()) {
787 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed has already been deleted and therefore cannot be accessed");
796 DLLLOCAL
void unlockParsing() {
799 if (!(--parse_count) && thread_waiting)
804 DLLLOCAL
void waitForAllThreadsToTerminateIntern() {
807 ptid_map_t::iterator i = tidmap.find(tid);
808 unsigned adj = (i != tidmap.end() ? 1 : 0);
810 while ((thread_count - adj) || parse_count) {
817 DLLLOCAL
void waitForAllThreadsToTerminate() {
820 waitForAllThreadsToTerminateIntern();
823 DLLLOCAL
const char* parseGetScriptPath()
const {
824 return script_path.empty() ? nullptr : script_path.c_str();
827 DLLLOCAL
const char* parseGetScriptDir()
const {
828 return script_dir.empty() ? nullptr : script_dir.c_str();
831 DLLLOCAL
const char* parseGetScriptName()
const {
832 return script_name.empty() ? nullptr : script_name.c_str();
838 return script_path.empty() ? nullptr :
new QoreStringNode(script_path);
844 return script_dir.empty() ? nullptr :
new QoreStringNode(script_dir);
850 return script_name.empty() ? nullptr :
new QoreStringNode(script_name);
853 DLLLOCAL
void setScriptPathExtern(
const char* path) {
859 DLLLOCAL
void setScriptPath(
const char* path) {
869 script_dir =
"." QORE_DIR_SEP_STR;
870 script_path = script_dir + script_name;
874 script_dir.assign(path, p - path);
889 for (CharPtrList::const_iterator i = featureList.begin(), e = featureList.end(); i != e; ++i)
892 for (CharPtrList::const_iterator i = userFeatureList.begin(), e = userFeatureList.end(); i != e; ++i)
901 DLLLOCAL
int internParsePending(
ExceptionSink* xsink,
const char* code,
const char* label,
const char* orig_src =
nullptr,
int offset = 0) {
904 assert(code && code[0]);
908 const char* sname = label;
909 const char* src = orig_src;
911 addFile(src, sname, offset);
916 QoreParseLocationHelper qplh(sname, src, offset);
923 beginParsing(sname,
nullptr, src, offset);
925 if (!parsing_in_progress) {
926 parsing_in_progress =
true;
935 yy_scan_string(code, lexer);
936 yyset_lineno(1, lexer);
940 printd(5,
"qore_program_private::internParsePending() returned from yyparse()\n");
944 printd(5,
"qore_program_private::internParsePending() parse exception: calling parseRollback()\n");
945 internParseRollback(xsink);
946 requires_exception =
false;
949 printd(5,
"qore_program_private::internParsePending() about to call yylex_destroy()\n");
950 yylex_destroy(lexer);
951 printd(5,
"qore_program_private::internParsePending() returned from yylex_destroy()\n");
960 if (pendingParseSink) {
962 pendingParseSink =
nullptr;
968 xsink->
raiseException(
"PARSE-ERROR",
"parsing can only happen once for each Program container");
974 DLLLOCAL
int parsePending(
const char* code,
const char* label,
ExceptionSink* xsink,
ExceptionSink* wS,
int wm,
const char* orig_src =
nullptr,
int offset = 0) {
977 ProgramRuntimeParseContextHelper pch(xsink, pgm);
983 if (checkParse(xsink)) {
987 startParsing(xsink, wS, wm);
989 int rc = internParsePending(xsink, code, label, orig_src, offset);
998 DLLLOCAL
int internParseCommit();
1001 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1007 if (checkParse(xsink)) {
1011 startParsing(xsink, wS, wm);
1014 int rc = internParseCommit();
1017 parseSink =
nullptr;
1025 ProgramRuntimeParseContextHelper pch(xsink, pgm);
1031 internParseRollback(xsink);
1037 printd(5,
"QoreProgram::parse(fp: %p, name: %s, xsink: %p, wS: %p, wm: %d)\n", fp, name, xsink, wS, wm);
1043 printd(5,
"QoreProgram::parse(fp: %p, name: %s) EOF\n", fp, name);
1052 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1057 if (checkParse(xsink)) {
1061 startParsing(xsink, wS, wm);
1065 const char* sname = name;
1068 QoreParseLocationHelper qplh(sname,
nullptr, 0);
1075 beginParsing(sname);
1077 if (!parsing_in_progress) {
1078 parsing_in_progress =
true;
1083 yyset_in(fp, lexer);
1088 internParseCommit();
1091 parseSink =
nullptr;
1097 yylex_destroy(lexer);
1098 if (only_first_except && exceptions_raised > 1)
1099 fprintf(stderr,
"\n%d exception(s) skipped\n\n", exceptions_raised);
1118 if (source && !source->empty() && !src.
set(source,
QCS_DEFAULT, xsink))
1121 parse(tstr->getBuffer(), tlstr->getBuffer(), xsink, wS, wm, source ? src->
getBuffer() : 0, offset);
1124 DLLLOCAL
void parse(
const char* code,
const char* label,
ExceptionSink* xsink,
ExceptionSink* wS,
int wm,
const char* orig_src = 0,
int offset = 0) {
1127 assert(code && code[0]);
1130 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1135 if (checkParse(xsink)) {
1139 startParsing(xsink, wS, wm);
1142 if (!internParsePending(xsink, code, label, orig_src, offset))
1143 internParseCommit();
1146 parseSink =
nullptr;
1152 QORE_TRACE(
"QoreProgram::parseFile()");
1154 printd(5,
"QoreProgram::parseFile(%s)\n", filename);
1157 if (!(fp = fopen(filename,
"r"))) {
1158 if ((only_first_except && !exceptions_raised) || !only_first_except)
1159 xsink->
raiseErrnoException(
"PARSE-EXCEPTION", errno,
"cannot open qore script '%s'", filename);
1160 exceptions_raised++;
1163 ON_BLOCK_EXIT(fclose, fp);
1165 setScriptPath(filename);
1167 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1171 parse(fp, filename, xsink, wS, wm);
1175 assert(!str->
empty());
1189 if (source && !source->empty() && !src.
set(source,
QCS_DEFAULT, xsink))
1192 parsePending(tstr->getBuffer(), tlstr->getBuffer(), xsink, wS, wm, source ? src->
getBuffer() : 0, offset);
1196 DLLLOCAL
void importFunction(
ExceptionSink* xsink, QoreFunction *u,
const qore_ns_private& oldns,
const char* new_name =
nullptr,
bool inject =
false);
1204 thread_local_storage->
set(h);
1212 printd(5,
"QoreProgram::clearThreadData() this: %p h: %p (size: %d)\n",
this, h, h ? h->
size() : 0);
1222 thread_local_storage->
set(0);
1226 DLLLOCAL
void finalizeThreadData(ThreadProgramData* td,
arg_vec_t*& cl) {
1232 thread_local_storage->
set(0);
1240 pgm_data_map_t::iterator i = pgm_data_map.find(td);
1241 if (i != pgm_data_map.end())
1242 i->second->finalize(cl);
1246 DLLLOCAL
int endThread(ThreadProgramData* td,
ExceptionSink* xsink) {
1247 ThreadLocalProgramData* tlpd = 0;
1255 pgm_data_map_t::iterator i = pgm_data_map.find(td);
1256 if (i == pgm_data_map.end())
1259 pgm_data_map.erase(i);
1266 DLLLOCAL
void doTopLevelInstantiation(ThreadLocalProgramData& tlpd) {
1268 const LVList* lvl = sb.getLVList();
1270 for (
unsigned i = 0; i < lvl->size(); ++i)
1271 lvl->lv[i]->instantiate();
1279 DLLLOCAL
bool setThreadVarData(ThreadProgramData* td, ThreadLocalProgramData*& new_tlpd,
bool run) {
1283 if (tclear ==
gettid()) {
1285 assert(pgm_data_map.find(td) != pgm_data_map.end());
1286 assert(pgm_data_map[td]->inst);
1294 pgm_data_map_t::iterator i = pgm_data_map.find(td);
1295 if (i == pgm_data_map.end()) {
1297 ThreadLocalProgramData* tlpd =
new ThreadLocalProgramData;
1299 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");
1303 pgm_data_map.insert(pgm_data_map_t::value_type(td, tlpd));
1308 printd(5,
"qore_program_private::setThreadVarData() (first) this: %p pgm: %p td: %p\n",
this, pgm, td);
1309 doTopLevelInstantiation(*tlpd);
1315 ThreadLocalProgramData* tlpd = pgm_data_map[td];
1320 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");
1322 if (run && !tlpd->inst) {
1323 doTopLevelInstantiation(*tlpd);
1329 DLLLOCAL
const AbstractQoreZoneInfo*
currentTZ(ThreadProgramData* tpd = get_thread_program_data())
const {
1331 pgm_data_map_t::const_iterator i = pgm_data_map.find(tpd);
1332 if (i != pgm_data_map.end() && i->second->tz_set)
1333 return i->second->tz;
1337 DLLLOCAL
void setTZ(
const AbstractQoreZoneInfo* n_TZ) {
1341 DLLLOCAL
void exportFunction(
ExceptionSink* xsink, qore_program_private* p,
const char* name,
const char* new_name =
nullptr,
bool inject =
false) {
1343 xsink->
raiseException(
"FUNCTION-IMPORT-ERROR",
"cannot import a function from the same Program object");
1348 xsink->
raiseException(
"FUNCTION-IMPORT-ERROR",
"cannot import function \"%s\" in a Program object without PO_ALLOW_INJECTION set", name);
1352 const QoreFunction* u;
1353 const qore_ns_private* ns =
nullptr;
1356 ProgramRuntimeParseAccessHelper rah(xsink, pgm);
1359 u = qore_root_ns_private::runtimeFindFunction(*RootNS, name, ns);
1363 xsink->
raiseException(
"PROGRAM-IMPORTFUNCTION-NO-FUNCTION",
"function '%s' does not exist in the current program scope", name);
1366 p->importFunction(xsink, const_cast<QoreFunction*>(u), *ns, new_name, inject);
1370 DLLLOCAL
bool parseExceptionRaised()
const {
1375 DLLLOCAL
void setParseOptionsIntern(
int64 po) {
1376 pwo.parse_options |= po;
1379 DLLLOCAL
void disableParseOptionsIntern(
int64 po) {
1380 pwo.parse_options &= ~po;
1383 DLLLOCAL
void replaceParseOptionsIntern(
int64 po) {
1384 pwo.parse_options = po;
1392 xsink->
raiseException(
"OPTIONS-LOCKED",
"parse options have been locked on this program object");
1396 setParseOptionsIntern(po);
1404 if (((po & PO_FREE_OPTIONS) != po) && po_locked && !po_allow_restrict) {
1405 xsink->
raiseException(
"OPTIONS-LOCKED",
"parse options have been locked on this program object");
1409 disableParseOptionsIntern(po);
1416 xsink->
raiseException(
"OPTION-ERROR",
"the calling Program does not have the PO_NO_CHILD_PO_RESTRICTIONS option set, and therefore cannot call Program::replaceParseOptions()");
1421 replaceParseOptionsIntern(po);
1425 DLLLOCAL
int parseSetParseOptions(
const QoreProgramLocation* loc,
int64 po) {
1428 if (((po & PO_FREE_OPTIONS) != po) && po_locked && (!po_allow_restrict || (po & PO_POSITIVE_OPTIONS))) {
1429 parse_error(*loc,
"parse options have been locked on this program object");
1433 setParseOptionsIntern(po);
1437 DLLLOCAL
int parseDisableParseOptions(
const QoreProgramLocation* loc,
int64 po) {
1440 if (((po & PO_FREE_OPTIONS) != po) && po_locked && !po_allow_restrict) {
1441 parse_error(*loc,
"parse options have been locked on this program object");
1445 disableParseOptionsIntern(po);
1449 DLLLOCAL
void parseSetTimeZone(
const char* zone) {
1453 mergeParseException(xsink);
1457 const AbstractQoreZoneInfo *tz = (*zone ==
'-' || *zone ==
'+') ? QTZM.findCreateOffsetZone(zone, &xsink) : QTZM.findLoadRegion(zone, &xsink);
1460 mergeParseException(xsink);
1464 assert(tz || ((*zone ==
'-' || *zone ==
'+')));
1469 DLLLOCAL
void makeParseException(
const QoreProgramLocation& loc,
const char* err,
QoreStringNode* desc) {
1470 QORE_TRACE(
"QoreProgram::makeParseException()");
1473 if (!requires_exception) {
1474 if ((only_first_except && !exceptions_raised) || !only_first_except) {
1475 QoreException *ne =
new ParseException(loc, err, d.release());
1478 exceptions_raised++;
1482 DLLLOCAL
void parseException(QoreProgramLocation& loc,
const char* fmt, ...) {
1486 if (requires_exception)
1492 va_start(args, fmt);
1493 int rc = desc->
vsprintf(fmt, args);
1498 makeParseException(loc,
"PARSE-EXCEPTION", desc);
1504 dmap_t::iterator i = dmap.find(name);
1505 if (i != dmap.end()) {
1506 i->second.discard(xsink);
1516 DLLLOCAL
const QoreValue getDefine(
const char* name,
bool& is_defined) {
1517 dmap_t::iterator i = dmap.find(name);
1518 if (i != dmap.end()) {
1526 DLLLOCAL
QoreValue runTimeGetDefine(
const char* name,
bool& is_defined) {
1528 return getDefine(name, is_defined).refSelf();
1535 DLLLOCAL
bool unDefine(
const char* name,
ExceptionSink* xsink) {
1536 dmap_t::iterator i = dmap.find(name);
1537 if (i != dmap.end()) {
1538 i->second.discard(xsink);
1545 DLLLOCAL
bool parseUnDefine(
const char* name) {
1546 PreParseHelper pph(
this);
1547 return unDefine(name, parseSink);
1550 DLLLOCAL
bool runTimeUnDefine(
const char* name,
ExceptionSink* xsink) {
1552 return unDefine(name, xsink);
1556 DLLLOCAL
bool isDefined(
const char* name) {
1557 dmap_t::iterator i = dmap.find(name);
1558 return i == dmap.end() ? false :
true;
1561 DLLLOCAL
bool runTimeIsDefined(
const char* name) {
1563 return isDefined(name);
1566 DLLLOCAL
int checkDefine(
const QoreProgramLocation* loc,
const char* str,
ExceptionSink* xsink) {
1567 const char* p = str;
1569 xsink->
raiseException(*loc,
"PARSE-EXCEPTION", 0,
"illegal define variable '%s'; does not begin with an alphabetic character", p);
1574 if (!isalnum(*p) && *p !=
'_') {
1576 xsink->
raiseException(*loc,
"PARSE-EXCEPTION", 0,
"illegal character '%c' in define variable '%s'", *p, str);
1584 DLLLOCAL
void parseDefine(
const QoreProgramLocation* loc,
const char* str,
QoreValue val) {
1585 PreParseHelper pph(
this);
1587 if (checkDefine(loc, str, parseSink))
1590 setDefine(str, val, parseSink);
1594 const QoreProgramLocation* loc = get_runtime_location();
1596 if (checkDefine(loc, str, xsink))
1600 setDefine(str, val, xsink);
1605 ProgramRuntimeParseAccessHelper pah(xsink, pgm);
1608 return qore_root_ns_private::runtimeGetCallReference(*RootNS, name, xsink);
1611 DLLLOCAL
void pushParseOptions(
const char* pf) {
1613 ppo_t::iterator i = ppo.lower_bound(pf);
1614 if (i != ppo.end() && !strcmp(pf, i->first))
1616 ppo.insert(i, ppo_t::value_type(pf, pwo.parse_options));
1620 DLLLOCAL
void restoreParseOptions(
const char* pf) {
1621 ppo_t::iterator i = ppo.find(pf);
1622 if (i != ppo.end()) {
1624 pwo.parse_options = i->second;
1629 DLLLOCAL
void addParseException(
ExceptionSink& xsink,
const QoreProgramLocation* loc) {
1630 if (requires_exception) {
1637 xsink.overrideLocation(*loc);
1645 assert(!(n_dom & PO_FREE_OPTIONS));
1653 if ((pos & p_tmp) != pos) {
1654 rv = ((pos & p_tmp) ^ pos);
1658 int64 neg = (n_dom & ~PO_POSITIVE_OPTIONS);
1659 if (neg && (neg & pwo.parse_options)) {
1660 rv |= (neg & pwo.parse_options);
1668 DLLLOCAL
void exportGlobalVariable(
const char* name,
bool readonly, qore_program_private& tpgm,
ExceptionSink* xsink);
1675 DLLLOCAL
void setThreadTZ(ThreadProgramData* tpd,
const AbstractQoreZoneInfo* tz) {
1677 pgm_data_map_t::iterator i = pgm_data_map.find(tpd);
1678 assert(i != pgm_data_map.end());
1679 i->second->setTZ(tz);
1682 DLLLOCAL
const AbstractQoreZoneInfo* getThreadTZ(ThreadProgramData* tpd,
bool&
set)
const {
1684 pgm_data_map_t::const_iterator i = pgm_data_map.find(tpd);
1685 assert(i != pgm_data_map.end());
1686 set = i->second->tz_set;
1687 return i->second->tz;
1690 DLLLOCAL
void clearThreadTZ(ThreadProgramData* tpd) {
1692 pgm_data_map_t::iterator i = pgm_data_map.find(tpd);
1693 assert(i != pgm_data_map.end());
1694 i->second->clearTZ();
1697 DLLLOCAL
void addStatement(AbstractStatement* s) {
1702 parse_error(*s->loc,
"illegal top-level statement (conflicts with parse option NO_TOP_LEVEL_STATEMENTS)");
1705 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);
1707 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);
1709 DLLLOCAL
const char* addString(
const char* str) {
1710 str_set_t::iterator i = str_set.lower_bound(str);
1711 if (i == str_set.end() || strcmp(*i, str)) {
1712 str_vec.push_back(strdup(str));
1713 i = str_set.insert(i, str_vec.back());
1718 DLLLOCAL
void addFile(
const char*& file) {
1719 file = addString(file);
1720 printd(5,
"qore_program_private::addFile('%s')\n", file);
1721 addStatementToIndexIntern(&statementByFileIndex, file,
nullptr, -1,
nullptr, -1);
1724 DLLLOCAL
void addFile(
const char*& file,
const char*& source,
int offset) {
1725 file = addString(file);
1727 source = addString(source);
1729 printd(5,
"qore_program_private::addFile('%s', '%s', %d)\n", file, source ? source :
"(null)", offset);
1730 addStatementToIndexIntern(&statementByFileIndex, file,
nullptr, -1, source, offset);
1732 addStatementToIndexIntern(&statementByLabelIndex, source,
nullptr, -1, file, offset);
1736 DLLLOCAL
void addUserFeature(
const char* f) {
1737 userFeatureList.push_back(f);
1740 DLLLOCAL
void runtimeImportSystemClassesIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1741 DLLLOCAL
void runtimeImportSystemConstantsIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1742 DLLLOCAL
void runtimeImportSystemFunctionsIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1743 DLLLOCAL
void runtimeImportSystemHashDeclsIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1745 DLLLOCAL
void runtimeImportSystemClasses(
ExceptionSink* xsink);
1746 DLLLOCAL
void runtimeImportSystemConstants(
ExceptionSink* xsink);
1747 DLLLOCAL
void runtimeImportSystemFunctions(
ExceptionSink* xsink);
1748 DLLLOCAL
void runtimeImportSystemHashDecls(
ExceptionSink* xsink);
1757 assert(extmap.find(owner) == extmap.end());
1758 extmap.insert(extmap_t::value_type(owner, pud));
1763 extmap_t::const_iterator i = extmap.find(owner);
1764 return i == extmap.end() ? nullptr : i->second;
1768 return qore_root_ns_private::getGlobalVars(*RootNS);
1771 DLLLOCAL LocalVar* createLocalVar(
const char* name,
const QoreTypeInfo* typeInfo);
1773 DLLLOCAL
const AbstractQoreFunctionVariant* runtimeFindCall(
const char* name,
const QoreListNode* params,
ExceptionSink* xsink);
1778 return pgm.priv->runtimeFindClass(class_name, xsink);
1782 pgm.priv->doThreadInit(xsink);
1787 if (!pgm.priv->exec_class) {
1788 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>))");
1791 pgm.priv->exec_class_rv.discard(xsink);
1792 pgm.priv->exec_class_rv = rv.release();
1798 return pgm.priv->preregisterNewThread(xsink);
1802 DLLLOCAL
static void cancelPreregistration(
QoreProgram& pgm) {
1803 pgm.priv->cancelPreregistration();
1807 DLLLOCAL
static void registerNewThread(
QoreProgram& pgm,
int tid) {
1808 pgm.priv->registerNewThread(tid);
1812 pgm.priv->runtimeImportSystemClasses(xsink);
1816 pgm.priv->runtimeImportSystemHashDecls(xsink);
1820 pgm.priv->runtimeImportSystemConstants(xsink);
1824 pgm.priv->runtimeImportSystemFunctions(xsink);
1828 pgm.priv->runtimeImportSystemApi(xsink);
1831 DLLLOCAL
static qore_program_private*
get(
QoreProgram& pgm) {
1836 pgm.priv->clearThreadData(xsink);
1839 DLLLOCAL
static void addUserFeature(
QoreProgram& pgm,
const char* f) {
1840 pgm.priv->addUserFeature(f);
1843 DLLLOCAL
static void addStatement(
QoreProgram& pgm, AbstractStatement* s) {
1844 pgm.priv->addStatement(s);
1847 DLLLOCAL
static const AbstractQoreZoneInfo* currentTZIntern(
QoreProgram& pgm) {
1848 return pgm.priv->TZ;
1852 return pgm.priv->lockParsing(xsink);
1855 DLLLOCAL
static void unlockParsing(
QoreProgram& pgm) {
1856 pgm.priv->unlockParsing();
1860 return pgm.priv->incThreadCount(xsink);
1863 DLLLOCAL
static void decThreadCount(
QoreProgram& pgm,
int tid) {
1864 pgm.priv->decThreadCount(tid);
1868 DLLLOCAL
static void addSignal(
QoreProgram& pgm,
int sig) {
1869 assert(pgm.priv->sigset.find(sig) == pgm.priv->sigset.end());
1870 pgm.priv->sigset.insert(sig);
1874 DLLLOCAL
static void delSignal(
QoreProgram& pgm,
int sig) {
1875 assert(pgm.priv->sigset.find(sig) != pgm.priv->sigset.end());
1876 pgm.priv->sigset.erase(sig);
1880 pgm.priv->qore_program_private_base::startThread(xsink);
1884 return pgm.priv->setThreadInit(n_thr_init, xsink);
1888 return pgm->priv->runtimeGetCallReference(name, xsink);
1891 DLLLOCAL
static const ParseWarnOptions& getParseWarnOptions(
const QoreProgram* pgm) {
1892 return pgm->priv->pwo;
1895 DLLLOCAL
static bool setSaveParseWarnOptions(
const QoreProgram* pgm,
const ParseWarnOptions &new_opts, ParseWarnOptions &old_opts) {
1896 if (new_opts == pgm->priv->pwo)
1898 old_opts = pgm->priv->pwo;
1899 pgm->priv->pwo = new_opts;
1903 DLLLOCAL
static void setParseWarnOptions(
const QoreProgram* pgm,
const ParseWarnOptions &new_opts) {
1904 pgm->priv->pwo = new_opts;
1907 DLLLOCAL
static bool setThreadVarData(
QoreProgram* pgm, ThreadProgramData* td, ThreadLocalProgramData* &tlpd,
bool run) {
1908 return pgm->priv->setThreadVarData(td, tlpd, run);
1911 DLLLOCAL
static void finalizeThreadData(
QoreProgram* pgm, ThreadProgramData* td,
arg_vec_t*& cl) {
1912 pgm->priv->finalizeThreadData(td, cl);
1916 return pgm->priv->endThread(td, xsink);
1920 pgm->priv->makeParseException(loc,
"PARSE-EXCEPTION", desc);
1923 DLLLOCAL
static void makeParseException(
QoreProgram* pgm,
const QoreProgramLocation &loc,
const char* err,
QoreStringNode* desc) {
1924 pgm->priv->makeParseException(loc, err, desc);
1929 return pgm->priv->getDefine(name, is_defined);
1932 DLLLOCAL
static const QoreValue parseGetDefine(
QoreProgram* pgm,
const char* name,
bool& is_defined) {
1933 return pgm->priv->getDefine(name, is_defined);
1938 return pgm->priv->runTimeGetDefine(name, is_defined);
1941 DLLLOCAL
static QoreValue runTimeGetDefine(
QoreProgram* pgm,
const char* name,
bool& is_defined) {
1942 return pgm->priv->runTimeGetDefine(name, is_defined);
1946 return pgm->priv->runTimeGetAllDefines();
1949 DLLLOCAL
static bool parseUnDefine(
QoreProgram* pgm,
const char* name) {
1950 return pgm->priv->parseUnDefine(name);
1954 return pgm->priv->runTimeUnDefine(name, xsink);
1957 DLLLOCAL
static bool parseIsDefined(
QoreProgram* pgm,
const char* name) {
1958 return pgm->priv->isDefined(name);
1961 DLLLOCAL
static bool runTimeIsDefined(
QoreProgram* pgm,
const char* name) {
1962 return pgm->priv->runTimeIsDefined(name);
1965 DLLLOCAL
static void parseDefine(
QoreProgram* pgm,
const QoreProgramLocation* loc,
const char* str,
QoreValue val) {
1966 pgm->priv->parseDefine(loc, str, val);
1970 pgm->priv->runTimeDefine(str, val, xsink);
1973 DLLLOCAL
static void addParseException(
QoreProgram* pgm,
ExceptionSink* xsink,
const QoreProgramLocation* loc =
nullptr) {
1975 pgm->priv->addParseException(*xsink, loc);
1979 DLLLOCAL
static void addParseException(
QoreProgram* pgm,
ExceptionSink& xsink,
const QoreProgramLocation* loc =
nullptr) {
1980 pgm->priv->addParseException(xsink, loc);
1983 DLLLOCAL
static void exportFunction(
QoreProgram* srcpgm,
ExceptionSink* xsink,
QoreProgram* trgpgm,
const char* name,
const char* new_name =
nullptr,
bool inject =
false) {
1984 srcpgm->priv->exportFunction(xsink, trgpgm->priv, name, new_name, inject);
1988 return pgm->priv->parseAddDomain(n_dom);
1992 return pgm.priv->dom;
1996 pgm.priv->dom |= n_dom;
2000 int64 rv = pgm.priv->pwo.parse_options;
2001 pgm.priv->pwo.parse_options = po;
2005 DLLLOCAL
static void makeParseWarning(
QoreProgram* pgm,
const QoreProgramLocation &loc,
int code,
const char* warn,
const char* fmt, ...) {
2007 if (!pgm->priv->warnSink || !(code & pgm->priv->pwo.warn_mask))
2013 va_start(args, fmt);
2014 int rc = desc->
vsprintf(fmt, args);
2019 QoreException *ne =
new ParseException(loc, warn, desc);
2020 pgm->priv->warnSink->raiseException(ne);
2023 DLLLOCAL
static void makeParseWarning(
QoreProgram* pgm,
const QoreProgramLocation &loc,
int code,
const char* warn,
QoreStringNode* desc) {
2025 if (!pgm->priv->warnSink || !(code & pgm->priv->pwo.warn_mask)) {
2030 QoreException *ne =
new ParseException(loc, warn, desc);
2031 pgm->priv->warnSink->raiseException(ne);
2035 pgm->priv->exportGlobalVariable(name, readonly, *(tpgm->priv), xsink);
2038 DLLLOCAL
void attachDebug(
const qore_debug_program_private* n_dpgm) {
2039 printd(5,
"qore_program_private::attachDebug(n_dpgm: %p), dpgm: %p\n", n_dpgm, dpgm);
2045 dpgm =
const_cast<qore_debug_program_private*
>(n_dpgm);
2046 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());
2047 for (
auto& i : pgm_data_map) {
2048 i.second->dbgPendingAttach();
2049 i.second->dbgBreak();
2053 DLLLOCAL
void detachDebug(
const qore_debug_program_private* n_dpgm) {
2054 printd(5,
"qore_program_private::detachDebug(n_dpgm: %p), dpgm: %p\n", n_dpgm, dpgm);
2057 assert(n_dpgm==dpgm);
2061 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());
2062 for (
auto& i : pgm_data_map) {
2063 i.second->dbgPendingDetach();
2068 DLLLOCAL
void onAttach(DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2069 DLLLOCAL
void onDetach(DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2070 DLLLOCAL
void onStep(
const StatementBlock *blockStatement,
const AbstractStatement *statement,
unsigned bkptId,
int &flow, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2071 DLLLOCAL
void onFunctionEnter(
const StatementBlock *statement, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2072 DLLLOCAL
void onFunctionExit(
const StatementBlock *statement,
QoreValue& returnValue, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2073 DLLLOCAL
void onException(
const AbstractStatement *statement, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2074 DLLLOCAL
void onExit(
const StatementBlock *statement,
QoreValue& returnValue, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2076 DLLLOCAL
int breakProgramThread(
int tid) {
2077 printd(5,
"qore_program_private::breakProgramThread(), this: %p, tid: %d\n",
this,
gettid());
2079 for (
auto& i : pgm_data_map) {
2080 if (i.first->gettid() == tid) {
2081 i.second->dbgBreak();
2088 DLLLOCAL
void breakProgram() {
2089 printd(5,
"qore_program_private::breakProgram(), this: %p\n",
this);
2091 for (
auto& i : pgm_data_map) {
2092 i.second->dbgBreak();
2097 if (!bkpt ||
this == bkpt->pgm)
return;
2098 if (!checkAllowDebugging(xsink))
2104 breakpointList.push_back(bkpt);
2109 DLLLOCAL
void deleteAllBreakpoints() {
2111 for (QoreBreakpointList_t::iterator it = breakpointList.begin(); it != breakpointList.end(); ++it) {
2112 (*it)->unassignAllStatements();
2113 (*it)->pgm =
nullptr;
2116 breakpointList.clear();
2119 DLLLOCAL
void getBreakpoints(QoreBreakpointList_t &bkptList) {
2122 for (QoreBreakpointList_t::iterator it = breakpointList.begin(); it != breakpointList.end(); ++it) {
2123 bkptList.push_back(*it);
2128 DLLLOCAL
void getStatementBreakpoints(
const AbstractStatement* statement, QoreBreakpointList_t &bkptList) {
2131 if (statement->breakpoints) {
2132 for (std::list<QoreBreakpoint*>::iterator it = statement->breakpoints->begin(); it != statement->breakpoints->end(); ++it) {
2133 bkptList.push_back(*it);
2139 DLLLOCAL
inline unsigned onCheckBreakpoint(
const AbstractStatement *statement,
ExceptionSink* xsink) {
2149 DLLLOCAL
unsigned long getStatementId(
const AbstractStatement* statement)
const {
2153 ReverseStatementIdMap_t::const_iterator i = reverseStatementIds.find((AbstractStatement*) statement);
2154 if (i == reverseStatementIds.end())
2161 if (statementId == 0 || statementId > statementIds.size())
2163 return statementIds[statementId-1];
2166 DLLLOCAL
unsigned getProgramId()
const {
2179 qore_root_ns_private::clearData(*RootNS, xsink);
2182 DLLLOCAL
static QoreProgram* resolveProgramId(
unsigned programId) {
2183 printd(5,
"qore_program_private::resolveProgramId(%x)\n", programId);
2185 for (qore_program_to_object_map_t::iterator i = qore_program_to_object_map.begin(); i != qore_program_to_object_map.end(); i++) {
2186 if (i->first->priv->programId == programId)
2195 xsink->
raiseException(
"DEBUGGING",
"program does not provide internal data for debugging");
2203 DLLLOCAL
void addStatementToIndexIntern(name_section_sline_statement_map_t* statementIndex,
const char* key, AbstractStatement *statement,
int offs,
const char* section,
int sectionOffs);
2204 DLLLOCAL
static void registerStatement(
QoreProgram *pgm, AbstractStatement *statement,
bool addToIndex);
2205 DLLLOCAL
QoreHashNode* getSourceIndicesIntern(name_section_sline_statement_map_t* statementIndex,
ExceptionSink* xsink)
const;
2207 return getSourceIndicesIntern(&statementByLabelIndex, xsink);
2210 return getSourceIndicesIntern(&statementByFileIndex, xsink);
2213 DLLLOCAL AbstractStatement* getStatementFromIndex(
const char* name,
int line) {
2214 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d), this: %p, file#: %d, label#: %d\n", name, line,
this, statementByFileIndex.size(), statementByLabelIndex.size());
2216 name_section_sline_statement_map_t::iterator it;
2217 if (statementByFileIndex.empty()) {
2220 bool addOffs =
true;
2221 if (!name || *name ==
'\0') {
2222 if (statementByFileIndex.size() != 1)
2224 it = statementByFileIndex.begin();
2226 size_t l = strlen(name);
2227 it = statementByFileIndex.find(name);
2228 if (it == statementByFileIndex.end()) {
2229 it = statementByLabelIndex.find(name);
2230 if (it == statementByLabelIndex.end()) {
2233 it = statementByFileIndex.begin();
2234 while (it != statementByFileIndex.end()) {
2235 size_t k = strlen(it->first);
2237 if (strcmp(name, it->first + k - l) == 0) {
2239 if (k == l || name[0] ==
'/' || it->first[k-l-1] ==
'/') {
2246 if (it == statementByFileIndex.end()) {
2247 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) no suffix match, this: %p\n", name, line,
this);
2250 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found by file suffix match, this: %p\n", name, line,
this);
2253 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found by label full match, this: %p\n", name, line,
this);
2256 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found by file full match, this: %p\n", name, line,
this);
2259 sline_statement_map_t *ssm = &it->second->statementMap;
2260 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found '%s', this: %p, ssm#: %d\n", name, line, it->first,
this, ssm->size());
2261 if (ssm->size() == 0)
2264 sline_statement_map_t::iterator li = ssm->upper_bound(line);
2265 if (li == ssm->begin()) {
2266 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) no statement found by line #1, this: %p\n", name, line,
this);
2272 AbstractStatement* st =
nullptr;
2275 if (ln != li->first) {
2279 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) {
2280 int n = li->second->loc->end_line - li->second->loc->start_line;
2293 if (li == ssm->begin())
2298 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);
2300 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) no statement found by line #2, this: %p\n", name, line,
this);
2306 printd(5,
"qore_program_private::registerQoreObject() pgm: %p, pgmid: %d\n", pgm, getProgramId());
2308 qore_program_to_object_map_t::iterator i = qore_program_private::qore_program_to_object_map.find(pgm);
2309 assert(i != qore_program_private::qore_program_to_object_map.end());
2310 if (i->second && i->second != o) {
2311 xsink->
raiseException(
"PROGRAM-ERROR",
"The Program has already assigned QoreObject");
2318 printd(5,
"qore_program_private::unregisterQoreObject() pgm: %p, pgmid: %d\n", pgm, getProgramId());
2320 qore_program_to_object_map_t::iterator i = qore_program_private::qore_program_to_object_map.find(pgm);
2321 assert(i != qore_program_private::qore_program_to_object_map.end());
2322 assert(i->second == o);
2323 i->second =
nullptr;
2328 qore_program_to_object_map_t::iterator i = qore_program_to_object_map.find(pgm);
2329 if (i == qore_program_to_object_map.end()) {
2338 qore_program_to_object_map_t::iterator i = qore_program_to_object_map.find(pgm);
2339 assert(i != qore_program_to_object_map.end());
2341 printd(5,
"qore_program_private::getQoreObject() pgm: %p, pgmid: %d, second: %p\n", i->first, i->first->getProgramId(), i->second);
2345 printd(5,
"qore_program_private::getQoreObject() pgm: %p, pgmid: %d, new second: %p\n", pgm, pgm->
getProgramId(), i->second);
2355 qore_program_to_object_map_t::iterator i = qore_program_to_object_map.begin();
2356 while (i != qore_program_to_object_map.end()) {
2358 printd(5,
"qore_program_private::getAllQoreObjects() pgm: %p, pgmid: %d, second: %p\n", i->first, i->first->getProgramId(), i->second);
2362 printd(5,
"qore_program_private::getAllQoreObjects() pgm: %p, pgmid: %d, new second: %p\n", i->first, i->first->getProgramId(), i->second);
2365 (*l)->push(i->second,
nullptr);
2372 class ParseWarnHelper :
public ParseWarnOptions {
2376 DLLLOCAL ParseWarnHelper(
const ParseWarnOptions &new_opts) {
2378 restore = pgm ? qore_program_private::setSaveParseWarnOptions(pgm, new_opts, *
this) : false;
2380 DLLLOCAL ~ParseWarnHelper() {
2382 qore_program_private::setParseWarnOptions(
getProgram(), *
this);
2386 typedef std::map<QoreProgram*, qore_program_private*> qore_program_map_t;
2389 class qore_debug_program_private {
2394 qore_program_map_t qore_program_map;
2397 DLLLOCAL qore_debug_program_private(
QoreDebugProgram *n_dpgm): dpgm(n_dpgm) {};
2398 DLLLOCAL ~qore_debug_program_private() {
2399 assert(qore_program_map.empty());
2403 if (!pgm->priv->checkAllowDebugging(xsink))
2406 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2407 printd(5,
"qore_debug_program_private::addProgram(), this: %p, pgm: %p, i: %p, end: %p\n",
this, pgm, i, qore_program_map.end());
2408 if (i != qore_program_map.end())
2410 qore_program_map.insert(qore_program_map_t::value_type(pgm, pgm->priv));
2412 pgm->priv->attachDebug(
this);
2417 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2418 printd(5,
"qore_debug_program_private::removeProgram(), this: %p, pgm: %p, i: %p, end: %p\n",
this, pgm, i, qore_program_map.end());
2419 if (i == qore_program_map.end())
2421 pgm->priv->detachDebug(
this);
2422 qore_program_map.erase(i);
2427 DLLLOCAL
void removeAllPrograms() {
2429 printd(5,
"qore_debug_program_private::removeAllPrograms(), this: %p\n",
this);
2430 qore_program_map_t::iterator i;
2431 while ((i = qore_program_map.begin()) != qore_program_map.end()) {
2432 qore_program_private* qpp = i->second;
2434 qore_program_map.erase(i);
2435 qpp->detachDebug(
this);
2442 printd(5,
"qore_debug_program_private::getAllProgramObjects(), this: %p\n",
this);
2444 qore_program_map_t::iterator i = qore_program_map.begin();
2445 while (i != qore_program_map.end()) {
2448 (*l)->push(o,
nullptr);
2455 DLLLOCAL
void onAttach(
QoreProgram *pgm, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2456 AutoQoreCounterDec ad(&debug_program_counter);
2457 dpgm->onAttach(pgm, rs, rts, xsink);
2459 DLLLOCAL
void onDetach(
QoreProgram *pgm, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2460 AutoQoreCounterDec ad(&debug_program_counter);
2461 dpgm->onDetach(pgm, rs, rts, xsink);
2469 DLLLOCAL
void onStep(
QoreProgram *pgm,
const StatementBlock *blockStatement,
const AbstractStatement *statement,
unsigned bkptId,
int &flow, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2470 AutoQoreCounterDec ad(&debug_program_counter);
2471 dpgm->
onStep(pgm, blockStatement, statement, bkptId, flow, rs, rts, xsink);
2474 DLLLOCAL
void onFunctionEnter(
QoreProgram *pgm,
const StatementBlock *statement, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2475 AutoQoreCounterDec ad(&debug_program_counter);
2481 DLLLOCAL
void onFunctionExit(
QoreProgram *pgm,
const StatementBlock *statement,
QoreValue& returnValue, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2482 AutoQoreCounterDec ad(&debug_program_counter);
2483 dpgm->
onFunctionExit(pgm, statement, returnValue, rs, rts, xsink);
2488 DLLLOCAL
void onException(
QoreProgram* pgm,
const AbstractStatement* statement, DebugRunStateEnum& rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2489 AutoQoreCounterDec ad(&debug_program_counter);
2490 dpgm->
onException(pgm, statement, rs, rts, xsink);
2495 DLLLOCAL
void onExit(
QoreProgram *pgm,
const StatementBlock *statement,
QoreValue& returnValue, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2496 AutoQoreCounterDec ad(&debug_program_counter);
2497 dpgm->
onExit(pgm, statement, returnValue, rs, rts, xsink);
2500 DLLLOCAL
int breakProgramThread(
QoreProgram* pgm,
int tid) {
2507 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2508 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);
2509 if (i == qore_program_map.end())
2511 if (i->second->breakProgramThread(tid))
2523 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2524 printd(5,
"qore_debug_program_private::breakProgram(), this: %p, pgm: %p, i: %p, end: %p\n",
this, pgm, i, qore_program_map.end());
2525 if (i == qore_program_map.end())
2527 i->second->breakProgram();
2531 DLLLOCAL
void waitForTerminationAndClear(
ExceptionSink* xsink) {
2532 removeAllPrograms();
2537 DLLLOCAL
int getInterruptedCount() {
2538 return debug_program_counter.
getCount();
provides a safe and exception-safe way to hold write locks in Qore, only to be used on the stack...
Definition: QoreRWLock.h:144
DLLEXPORT int reference_count() const
gets the reference count
provides access to thread-local storage
Definition: QoreThreadLocalStorage.h:44
DLLEXPORT void assignProgram(QoreProgram *new_pgm, ExceptionSink *xsink)
abstract base class for c++ Exceptions in the Qore library
Definition: QoreStandardException.h:47
DLLEXPORT bool empty() const
returns true if the string is empty, false if not
This is the hash or associative list container type in Qore, dynamically allocated only...
Definition: QoreHashNode.h:50
a simple thread-safe counter object; objects can block on it until the counter reaches zero ...
Definition: QoreCounter.h:40
DLLEXPORT const QoreEncoding * QCS_DEFAULT
the default encoding for the Qore library
DLLLOCAL T * get()
retrieves the key's value
Definition: QoreThreadLocalStorage.h:77
DLLEXPORT AbstractStatement * resolveStatementId(unsigned long statementId, ExceptionSink *xsink) const
#define PO_NO_DEBUGGING
disallows debugging actions that could be insecure such as reading the thread local variable stack ...
Definition: Restrictions.h:86
Class implementing breakpoint for debugging.
Definition: QoreProgram.h:1009
DLLEXPORT int gettid() noexcept
returns the current TID number
virtual DLLEXPORT void deref(ExceptionSink *xsink)
decrements the reference count of the object
non-thread-safe vector for storing "char*" that you want to delete
Definition: common.h:238
DLLEXPORT unsigned getProgramId() const
get the program id
contains constants, classes, and subnamespaces in QoreProgram objects
Definition: QoreNamespace.h:64
virtual DLLEXPORT void onStep(QoreProgram *pgm, const StatementBlock *blockStatement, const AbstractStatement *statement, unsigned bkptId, int &flow, DebugRunStateEnum &rs, const AbstractStatement *&rts, ExceptionSink *xsink)
#define PO_NO_LOCALE_CONTROL
do not allow changes to program locale
Definition: Restrictions.h:64
#define PO_ALLOW_INJECTION
allow code injection
Definition: Restrictions.h:76
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...
#define PO_NO_TOP_LEVEL_STATEMENTS
cannot define new top-level statements (outside of sub or class defs)
Definition: Restrictions.h:44
DLLEXPORT int push(QoreValue val, ExceptionSink *xsink)
adds a value to the list
a thread condition class implementing a wrapper for pthread_cond_t
Definition: QoreCondition.h:45
DLLEXPORT bool ROdereference() const
atomically decrements the reference count
Qore's string type supported by the QoreEncoding class.
Definition: QoreString.h:81
Qore's string value type, reference counted, dynamically-allocated only.
Definition: QoreStringNode.h:50
DLLEXPORT int broadcast()
singles all threads blocked on this condition to wake up
#define PO_POSITIVE_OPTIONS
mask of all options allowing for more freedom (instead of less)
Definition: Restrictions.h:127
DLLEXPORT const char * getBuffer() const
returns the string's buffer; this data should not be changed
DLLEXPORT QoreProgram * getProgram()
returns the current QoreProgram
virtual DLLEXPORT void onFunctionEnter(QoreProgram *pgm, const StatementBlock *statement, DebugRunStateEnum &rs, const AbstractStatement *&rts, ExceptionSink *xsink)
the root namespace of a QoreProgram object
Definition: QoreNamespace.h:286
provides a safe and exception-safe way to hold locks in Qore, only to be used on the stack...
Definition: QoreThreadLock.h:128
This is the list container type in Qore, dynamically allocated only, reference counted.
Definition: QoreListNode.h:52
provides atomic reference counting to Qore objects
Definition: QoreReferenceCounter.h:44
defines a Qore-language class
Definition: QoreClass.h:237
DLLEXPORT qore_size_t strlen() const
returns number of bytes in the string (not including the null pointer)
an abstract class for program-specific external data
Definition: QoreProgram.h:985
DLLEXPORT int dec(ExceptionSink *xsink)
decrements the counter and wakes up any threads if the counter reaches 0
provides a safe and exception-safe way to hold read locks in Qore, only to be used on the stack...
Definition: QoreRWLock.h:105
supports parsing and executing Qore-language code, reference counted, dynamically-allocated only ...
Definition: QoreDebugProgram.h:66
DLLEXPORT int getCount() const
returns the current count
use this class to manage strings where the character encoding must be specified and may be different ...
Definition: QoreString.h:1015
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:262
supports parsing and executing Qore-language code, reference counted, dynamically-allocated only ...
Definition: QoreProgram.h:126
DLLEXPORT void clear()
deletes the exception list immediately
static DLLEXPORT QoreObject * getQoreObject(QoreProgram *pgm)
get QoreObject of QoreProgram
the implementation of Qore's object data type, reference counted, dynamically-allocated only ...
Definition: QoreObject.h:61
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:46
#define PO_FREE_OPTIONS
mask of options that have no effect on code access or code safety
Definition: Restrictions.h:130
virtual DLLEXPORT void onException(QoreProgram *pgm, const AbstractStatement *statement, DebugRunStateEnum &rs, const AbstractStatement *&rts, ExceptionSink *xsink)
DLLEXPORT unsigned getBreakpointId() const
get the breakpoint id
DLLEXPORT const QoreTypeInfo * getTypeInfo() const
returns the type information structure for this class
DLLEXPORT int inc()
increments the counter
virtual DLLEXPORT void onExit(QoreProgram *pgm, const StatementBlock *statement, QoreValue &returnValue, DebugRunStateEnum &rs, const AbstractStatement *&rts, ExceptionSink *xsink)
DLLEXPORT void deref(ExceptionSink *xsink)
decrements the reference count and calls derefImpl() if there_can_be_only_one is false, otherwise does nothing
long long int64
64bit integer type, cannot use int64_t here since it breaks the API on some 64-bit systems due to equ...
Definition: common.h:260
std::vector< QoreValue > arg_vec_t
vector of value information for default argument lists
Definition: common.h:254
DLLLOCAL void ref()
increments the reference count of the object
Definition: AbstractPrivateData.h:53
typed hash declaration
Definition: TypedHashDecl.h:44
DLLEXPORT void ROreference() const
atomically increments the reference count
base class for resolved call references
Definition: CallReferenceNode.h:105
DLLEXPORT QoreHashNode * copy() const
performs a copy of the hash and returns the new hash
DLLEXPORT qore_size_t size() const
returns the number of members in the hash, executes in constant time
provides a mutually-exclusive thread lock
Definition: QoreThreadLock.h:47
provides a simple POSIX-threads-based read-write lock
Definition: QoreRWLock.h:47
std::set< int > int_set_t
set of integers
Definition: common.h:82
DLLEXPORT int waitForZero(ExceptionSink *xsink, int timeout_ms=0)
blocks the calling thread until the counter reaches 0
DLLEXPORT char * q_basenameptr(const char *path)
returns a pointer within the same string
virtual DLLEXPORT void onFunctionExit(QoreProgram *pgm, const StatementBlock *statement, QoreValue &returnValue, DebugRunStateEnum &rs, const AbstractStatement *&rts, ExceptionSink *xsink)
DLLEXPORT bool isException() const
returns true if at least one exception is present
DLLLOCAL void set(T *ptr)
sets the key's value
Definition: QoreThreadLocalStorage.h:82
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:1092
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...
holds an object and dereferences it in the destructor
Definition: QoreValue.h:452
provides an exception-safe way to manage locks in Qore, only to be used on the stack, cannot be dynamically allocated
Definition: QoreThreadLock.h:230
DLLEXPORT int wait(pthread_mutex_t *m)
blocks a thread on a mutex until the condition is signaled
#define PO_NO_CHILD_PO_RESTRICTIONS
turn off parse option inheritance restrictions
Definition: Restrictions.h:51
DLLEXPORT void assimilate(ExceptionSink *xs)
assimilates all entries of the "xs" argument by appending them to the internal list and deletes the "...
DLLEXPORT const AbstractQoreZoneInfo * currentTZ()
returns the current local time zone, note that if 0 = UTC
DLLEXPORT QoreListNode * copy() const
performs a deep copy of the list and returns the new list