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;
127 const AbstractStatement* runToStatement;
129 int functionCallLevel;
131 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;
143 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() : runState(DBG_RS_DETACH), functionCallLevel(0), breakFlag(false), tz(0), 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(cl);
193 cvstack.finalize(cl);
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;
416 qpgm_thread_local_storage_t* thread_local_storage;
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 (pgm_data_map_t::iterator i = pgm_data_map.begin(), e = pgm_data_map.end(); i != e; ++i)
652 i->second->finalize(cl);
657 for (arg_vec_t::iterator i = cl->begin(), e = cl->end(); i != e; ++i) {
665 for (pgm_data_map_t::iterator i = pgm_data_map.begin(), e = pgm_data_map.end(); i != e; ++i) {
666 i->second->del(xsink);
667 i->first->delProgram(pgm);
671 DLLLOCAL
void waitForTerminationAndClear(
ExceptionSink* xsink);
683 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed has already been deleted and therefore no new threads can be started in it");
692 DLLLOCAL
void cancelPreregistration() {
696 assert(thread_count > 0);
697 if (!--thread_count && thread_waiting)
702 DLLLOCAL
void registerNewThread(
int tid) {
706 assert(thread_count);
727 if (ptid && ptid != tid) {
728 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed has already been deleted and therefore cannot be accessed at runtime");
731 if (parsing_in_progress) {
732 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed is currently undergoing parsing and cannot be accessed at runtime");
741 DLLLOCAL
void incThreadCount() {
747 if (ptid && ptid != tid) {
748 throw QoreStandardException(
"PROGRAM-ERROR",
"the Program accessed has already been deleted and therefore cannot be accessed at runtime");
750 if (parsing_in_progress) {
751 throw QoreStandardException(
"PROGRAM-ERROR",
"the Program accessed is currently undergoing parsing and cannot be accessed at runtime");
758 DLLLOCAL
void decThreadCount(
int tid) {
762 ptid_map_t::iterator i = tidmap.find(tid);
763 assert(i != tidmap.end());
767 assert(thread_count > 0);
768 if (!--thread_count && thread_waiting)
777 for (
auto& i : tidmap) {
778 l.
push(i.first,
nullptr);
788 while (parse_count) {
795 if (ptid && ptid !=
gettid()) {
797 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed has already been deleted and therefore cannot be accessed");
806 DLLLOCAL
void unlockParsing() {
809 if (!(--parse_count) && thread_waiting)
814 DLLLOCAL
void waitForAllThreadsToTerminateIntern() {
817 ptid_map_t::iterator i = tidmap.find(tid);
818 unsigned adj = (i != tidmap.end() ? 1 : 0);
820 while ((thread_count - adj) || parse_count) {
827 DLLLOCAL
void waitForAllThreadsToTerminate() {
830 waitForAllThreadsToTerminateIntern();
833 DLLLOCAL
const char* parseGetScriptPath()
const {
834 return script_path.empty() ? nullptr : script_path.c_str();
837 DLLLOCAL
const char* parseGetScriptDir()
const {
838 return script_dir.empty() ? nullptr : script_dir.c_str();
841 DLLLOCAL
const char* parseGetScriptName()
const {
842 return script_name.empty() ? nullptr : script_name.c_str();
848 return script_path.empty() ? nullptr :
new QoreStringNode(script_path);
854 return script_dir.empty() ? nullptr :
new QoreStringNode(script_dir);
860 return script_name.empty() ? nullptr :
new QoreStringNode(script_name);
863 DLLLOCAL
void setScriptPathExtern(
const char* path) {
869 DLLLOCAL
void setScriptPath(
const char* path) {
879 script_dir =
"." QORE_DIR_SEP_STR;
880 script_path = script_dir + script_name;
884 script_dir.assign(path, p - path);
899 for (CharPtrList::const_iterator i = featureList.begin(), e = featureList.end(); i != e; ++i)
902 for (CharPtrList::const_iterator i = userFeatureList.begin(), e = userFeatureList.end(); i != e; ++i)
911 DLLLOCAL
int internParsePending(
ExceptionSink* xsink,
const char* code,
const char* label,
const char* orig_src =
nullptr,
int offset = 0,
bool standard_parse =
true) {
914 assert(code && code[0]);
918 const char* sname = label;
919 const char* src = orig_src;
921 addFile(src, sname, offset);
926 QoreParseLocationHelper qplh(sname, src, offset);
933 beginParsing(sname,
nullptr, src, offset);
935 if (!parsing_in_progress) {
936 parsing_in_progress =
true;
945 yy_scan_string(code, lexer);
946 yyset_lineno(1, lexer);
950 printd(5,
"qore_program_private::internParsePending() returned from yyparse()\n");
954 if (standard_parse) {
955 printd(5,
"qore_program_private::internParsePending() parse exception: calling parseRollback()\n");
956 internParseRollback(xsink);
957 requires_exception =
false;
961 printd(5,
"qore_program_private::internParsePending() about to call yylex_destroy()\n");
962 yylex_destroy(lexer);
963 printd(5,
"qore_program_private::internParsePending() returned from yylex_destroy()\n");
972 if (pendingParseSink) {
974 pendingParseSink =
nullptr;
980 xsink->
raiseException(
"PARSE-ERROR",
"parsing can only happen once for each Program container");
986 DLLLOCAL
int parsePending(
const char* code,
const char* label,
ExceptionSink* xsink,
ExceptionSink* wS,
int wm,
const char* orig_src =
nullptr,
int offset = 0) {
989 ProgramRuntimeParseContextHelper pch(xsink, pgm);
995 if (checkParse(xsink)) {
999 startParsing(xsink, wS, wm);
1001 int rc = internParsePending(xsink, code, label, orig_src, offset);
1004 parseSink =
nullptr;
1010 DLLLOCAL
int internParseCommit(
bool standard_parse =
true);
1013 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1019 if (checkParse(xsink)) {
1023 startParsing(xsink, wS, wm);
1026 int rc = internParseCommit();
1029 parseSink =
nullptr;
1037 ProgramRuntimeParseContextHelper pch(xsink, pgm);
1043 internParseRollback(xsink);
1049 printd(5,
"QoreProgram::parse(fp: %p, name: %s, xsink: %p, wS: %p, wm: %d)\n", fp, name, xsink, wS, wm);
1055 printd(5,
"QoreProgram::parse(fp: %p, name: %s) EOF\n", fp, name);
1064 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1069 if (checkParse(xsink)) {
1073 startParsing(xsink, wS, wm);
1077 const char* sname = name;
1080 QoreParseLocationHelper qplh(sname,
nullptr, 0);
1087 beginParsing(sname);
1089 if (!parsing_in_progress) {
1090 parsing_in_progress =
true;
1095 yyset_in(fp, lexer);
1100 internParseCommit();
1103 parseSink =
nullptr;
1109 yylex_destroy(lexer);
1110 if (only_first_except && exceptions_raised > 1)
1111 fprintf(stderr,
"\n%d exception(s) skipped\n\n", exceptions_raised);
1130 if (source && !source->empty() && !src.
set(source,
QCS_DEFAULT, xsink))
1133 parse(tstr->getBuffer(), tlstr->getBuffer(), xsink, wS, wm, source ? src->
getBuffer() : 0, offset);
1136 DLLLOCAL
void parse(
const char* code,
const char* label,
ExceptionSink* xsink,
ExceptionSink* wS,
int wm,
const char* orig_src = 0,
int offset = 0) {
1139 assert(code && code[0]);
1142 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1147 if (checkParse(xsink)) {
1151 startParsing(xsink, wS, wm);
1154 if (!internParsePending(xsink, code, label, orig_src, offset))
1155 internParseCommit();
1158 parseSink =
nullptr;
1167 xsink->
raiseException(
"EXPRESSION-ERROR",
"the expression cannot be empty");
1182 if (source && !source->empty() && !src.
set(source,
QCS_DEFAULT, xsink))
1185 return parseExpression(tstr->c_str(), tlstr->c_str(), xsink, wS, wm, source ? src->
c_str() :
nullptr, offset);
1188 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) {
1191 assert(code && code[0]);
1194 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1199 assert(!expression_mode);
1200 assert(!new_expression);
1201 expression_mode =
true;
1203 QoreStringMaker exp_code(
"return (%s);", code);
1205 startParsing(xsink, wS, wm);
1208 if (!internParsePending(xsink, exp_code.c_str(), label, orig_src, offset,
false)) {
1209 internParseCommit(
false);
1211 parsing_in_progress =
false;
1215 parseSink =
nullptr;
1219 expression_mode =
false;
1220 q_exp_t rv = new_expression;
1221 if (new_expression) {
1223 exp_set.erase(new_expression);
1224 delete new_expression;
1227 new_expression =
nullptr;
1233 QORE_TRACE(
"QoreProgram::parseFile()");
1235 printd(5,
"QoreProgram::parseFile(%s)\n", filename);
1238 if (!(fp = fopen(filename,
"r"))) {
1239 if ((only_first_except && !exceptions_raised) || !only_first_except)
1240 xsink->
raiseErrnoException(
"PARSE-EXCEPTION", errno,
"cannot open qore script '%s'", filename);
1241 exceptions_raised++;
1244 ON_BLOCK_EXIT(fclose, fp);
1246 setScriptPath(filename);
1248 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1252 parse(fp, filename, xsink, wS, wm);
1256 assert(!str->
empty());
1270 if (source && !source->empty() && !src.
set(source,
QCS_DEFAULT, xsink))
1273 parsePending(tstr->getBuffer(), tlstr->getBuffer(), xsink, wS, wm, source ? src->
getBuffer() : 0, offset);
1277 DLLLOCAL
void importFunction(
ExceptionSink* xsink, QoreFunction *u,
const qore_ns_private& oldns,
const char* new_name =
nullptr,
bool inject =
false);
1285 thread_local_storage->
set(h);
1293 printd(5,
"QoreProgram::clearThreadData() this: %p h: %p (size: %d)\n",
this, h, h ? h->
size() : 0);
1303 thread_local_storage->
set(0);
1307 DLLLOCAL
void finalizeThreadData(ThreadProgramData* td,
arg_vec_t*& cl) {
1313 thread_local_storage->
set(0);
1321 pgm_data_map_t::iterator i = pgm_data_map.find(td);
1322 if (i != pgm_data_map.end())
1323 i->second->finalize(cl);
1327 DLLLOCAL
int endThread(ThreadProgramData* td,
ExceptionSink* xsink) {
1328 ThreadLocalProgramData* tlpd = 0;
1336 pgm_data_map_t::iterator i = pgm_data_map.find(td);
1337 if (i == pgm_data_map.end())
1340 pgm_data_map.erase(i);
1347 DLLLOCAL
void doTopLevelInstantiation(ThreadLocalProgramData& tlpd) {
1349 const LVList* lvl = sb.getLVList();
1351 for (
unsigned i = 0; i < lvl->size(); ++i)
1352 lvl->lv[i]->instantiate();
1360 DLLLOCAL
bool setThreadVarData(ThreadProgramData* td, ThreadLocalProgramData*& new_tlpd,
bool run) {
1364 if (tclear ==
gettid()) {
1366 assert(pgm_data_map.find(td) != pgm_data_map.end());
1367 assert(pgm_data_map[td]->inst);
1375 pgm_data_map_t::iterator i = pgm_data_map.find(td);
1376 if (i == pgm_data_map.end()) {
1378 ThreadLocalProgramData* tlpd =
new ThreadLocalProgramData;
1380 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");
1384 pgm_data_map.insert(pgm_data_map_t::value_type(td, tlpd));
1389 printd(5,
"qore_program_private::setThreadVarData() (first) this: %p pgm: %p td: %p\n",
this, pgm, td);
1390 doTopLevelInstantiation(*tlpd);
1396 ThreadLocalProgramData* tlpd = pgm_data_map[td];
1401 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");
1403 if (run && !tlpd->inst) {
1404 doTopLevelInstantiation(*tlpd);
1410 DLLLOCAL
const AbstractQoreZoneInfo*
currentTZ(ThreadProgramData* tpd = get_thread_program_data())
const {
1412 pgm_data_map_t::const_iterator i = pgm_data_map.find(tpd);
1413 if (i != pgm_data_map.end() && i->second->tz_set)
1414 return i->second->tz;
1418 DLLLOCAL
void setTZ(
const AbstractQoreZoneInfo* n_TZ) {
1422 DLLLOCAL
void exportFunction(
ExceptionSink* xsink, qore_program_private* p,
const char* name,
const char* new_name =
nullptr,
bool inject =
false) {
1424 xsink->
raiseException(
"FUNCTION-IMPORT-ERROR",
"cannot import a function from the same Program object");
1429 xsink->
raiseException(
"FUNCTION-IMPORT-ERROR",
"cannot import function \"%s\" in a Program object without PO_ALLOW_INJECTION set", name);
1433 const QoreFunction* u;
1434 const qore_ns_private* ns =
nullptr;
1437 ProgramRuntimeParseAccessHelper rah(xsink, pgm);
1440 u = qore_root_ns_private::runtimeFindFunction(*RootNS, name, ns);
1444 xsink->
raiseException(
"PROGRAM-IMPORTFUNCTION-NO-FUNCTION",
"function '%s' does not exist in the current program scope", name);
1447 p->importFunction(xsink, const_cast<QoreFunction*>(u), *ns, new_name, inject);
1451 DLLLOCAL
bool parseExceptionRaised()
const {
1456 DLLLOCAL
void setParseOptionsIntern(
int64 po) {
1457 pwo.parse_options |= po;
1460 DLLLOCAL
void disableParseOptionsIntern(
int64 po) {
1461 pwo.parse_options &= ~po;
1464 DLLLOCAL
void replaceParseOptionsIntern(
int64 po) {
1465 pwo.parse_options = po;
1473 xsink->
raiseException(
"OPTIONS-LOCKED",
"parse options have been locked on this program object");
1477 setParseOptionsIntern(po);
1485 if (((po & PO_FREE_OPTIONS) != po) && po_locked && !po_allow_restrict) {
1486 xsink->
raiseException(
"OPTIONS-LOCKED",
"parse options have been locked on this program object");
1490 disableParseOptionsIntern(po);
1497 xsink->
raiseException(
"OPTION-ERROR",
"the calling Program does not have the PO_NO_CHILD_PO_RESTRICTIONS option set, and therefore cannot call Program::replaceParseOptions()");
1502 replaceParseOptionsIntern(po);
1506 DLLLOCAL
int parseSetParseOptions(
const QoreProgramLocation* loc,
int64 po) {
1509 if (((po & PO_FREE_OPTIONS) != po) && po_locked && (!po_allow_restrict || (po & PO_POSITIVE_OPTIONS))) {
1510 parse_error(*loc,
"parse options have been locked on this program object");
1514 setParseOptionsIntern(po);
1518 DLLLOCAL
int parseDisableParseOptions(
const QoreProgramLocation* loc,
int64 po) {
1521 if (((po & PO_FREE_OPTIONS) != po) && po_locked && !po_allow_restrict) {
1522 parse_error(*loc,
"parse options have been locked on this program object");
1526 disableParseOptionsIntern(po);
1530 DLLLOCAL
void parseSetTimeZone(
const char* zone) {
1534 mergeParseException(xsink);
1538 const AbstractQoreZoneInfo *tz = (*zone ==
'-' || *zone ==
'+') ? QTZM.findCreateOffsetZone(zone, &xsink) : QTZM.findLoadRegion(zone, &xsink);
1541 mergeParseException(xsink);
1545 assert(tz || ((*zone ==
'-' || *zone ==
'+')));
1550 DLLLOCAL
void makeParseException(
const QoreProgramLocation& loc,
const char* err,
QoreStringNode* desc) {
1551 QORE_TRACE(
"QoreProgram::makeParseException()");
1554 if (!requires_exception) {
1555 if ((only_first_except && !exceptions_raised) || !only_first_except) {
1556 QoreException *ne =
new ParseException(loc, err, d.release());
1559 exceptions_raised++;
1563 DLLLOCAL
void parseException(QoreProgramLocation& loc,
const char* fmt, ...) {
1567 if (requires_exception)
1573 va_start(args, fmt);
1574 int rc = desc->
vsprintf(fmt, args);
1579 makeParseException(loc,
"PARSE-EXCEPTION", desc);
1585 dmap_t::iterator i = dmap.find(name);
1586 if (i != dmap.end()) {
1587 i->second.discard(xsink);
1597 DLLLOCAL
const QoreValue getDefine(
const char* name,
bool& is_defined) {
1598 dmap_t::iterator i = dmap.find(name);
1599 if (i != dmap.end()) {
1607 DLLLOCAL
QoreValue runTimeGetDefine(
const char* name,
bool& is_defined) {
1609 return getDefine(name, is_defined).refSelf();
1616 DLLLOCAL
bool unDefine(
const char* name,
ExceptionSink* xsink) {
1617 dmap_t::iterator i = dmap.find(name);
1618 if (i != dmap.end()) {
1619 i->second.discard(xsink);
1626 DLLLOCAL
bool parseUnDefine(
const char* name) {
1627 PreParseHelper pph(
this);
1628 return unDefine(name, parseSink);
1631 DLLLOCAL
bool runTimeUnDefine(
const char* name,
ExceptionSink* xsink) {
1633 return unDefine(name, xsink);
1637 DLLLOCAL
bool isDefined(
const char* name) {
1638 dmap_t::iterator i = dmap.find(name);
1639 return i == dmap.end() ? false :
true;
1642 DLLLOCAL
bool runTimeIsDefined(
const char* name) {
1644 return isDefined(name);
1647 DLLLOCAL
int checkDefine(
const QoreProgramLocation* loc,
const char* str,
ExceptionSink* xsink) {
1648 const char* p = str;
1650 xsink->
raiseException(*loc,
"PARSE-EXCEPTION", 0,
"illegal define variable '%s'; does not begin with an alphabetic character", p);
1655 if (!isalnum(*p) && *p !=
'_') {
1657 xsink->
raiseException(*loc,
"PARSE-EXCEPTION", 0,
"illegal character '%c' in define variable '%s'", *p, str);
1665 DLLLOCAL
void parseDefine(
const QoreProgramLocation* loc,
const char* str,
QoreValue val) {
1666 PreParseHelper pph(
this);
1668 if (checkDefine(loc, str, parseSink))
1671 setDefine(str, val, parseSink);
1675 const QoreProgramLocation* loc = get_runtime_location();
1677 if (checkDefine(loc, str, xsink))
1681 setDefine(str, val, xsink);
1686 ProgramRuntimeParseAccessHelper pah(xsink, pgm);
1689 return qore_root_ns_private::runtimeGetCallReference(*RootNS, name, xsink);
1692 DLLLOCAL
void pushParseOptions(
const char* pf) {
1694 ppo_t::iterator i = ppo.lower_bound(pf);
1695 if (i != ppo.end() && !strcmp(pf, i->first))
1697 ppo.insert(i, ppo_t::value_type(pf, pwo.parse_options));
1701 DLLLOCAL
void restoreParseOptions(
const char* pf) {
1702 ppo_t::iterator i = ppo.find(pf);
1703 if (i != ppo.end()) {
1705 pwo.parse_options = i->second;
1710 DLLLOCAL
void addParseException(
ExceptionSink& xsink,
const QoreProgramLocation* loc) {
1711 if (requires_exception) {
1718 xsink.overrideLocation(*loc);
1726 assert(!(n_dom & PO_FREE_OPTIONS));
1734 if ((pos & p_tmp) != pos) {
1735 rv = ((pos & p_tmp) ^ pos);
1739 int64 neg = (n_dom & ~PO_POSITIVE_OPTIONS);
1740 if (neg && (neg & pwo.parse_options)) {
1741 rv |= (neg & pwo.parse_options);
1749 DLLLOCAL
void exportGlobalVariable(
const char* name,
bool readonly, qore_program_private& tpgm,
ExceptionSink* xsink);
1756 DLLLOCAL
void setThreadTZ(ThreadProgramData* tpd,
const AbstractQoreZoneInfo* tz) {
1758 pgm_data_map_t::iterator i = pgm_data_map.find(tpd);
1759 assert(i != pgm_data_map.end());
1760 i->second->setTZ(tz);
1763 DLLLOCAL
const AbstractQoreZoneInfo* getThreadTZ(ThreadProgramData* tpd,
bool&
set)
const {
1765 pgm_data_map_t::const_iterator i = pgm_data_map.find(tpd);
1766 assert(i != pgm_data_map.end());
1767 set = i->second->tz_set;
1768 return i->second->tz;
1771 DLLLOCAL
void clearThreadTZ(ThreadProgramData* tpd) {
1773 pgm_data_map_t::iterator i = pgm_data_map.find(tpd);
1774 assert(i != pgm_data_map.end());
1775 i->second->clearTZ();
1778 DLLLOCAL
void addStatement(AbstractStatement* s);
1781 return parseExpression(source, label, xsink);
1785 ProgramThreadCountContextHelper pch(xsink, pgm,
true);
1789 if (exp_set.find(exp) == exp_set.end()) {
1790 xsink->
raiseException(
"INVALID-EXPRESSION",
"expression not registered to this Program object");
1793 ThreadFrameBoundaryHelper tfbh(
true);
1799 return rv.release();
1802 DLLLOCAL
void deleteExpression(q_exp_t exp) {
1804 q_exp_set_t::iterator i = exp_set.find(exp);
1805 if (i != exp_set.end()) {
1811 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);
1813 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);
1815 DLLLOCAL
const char* addString(
const char* str) {
1816 str_set_t::iterator i = str_set.lower_bound(str);
1817 if (i == str_set.end() || strcmp(*i, str)) {
1818 str_vec.push_back(strdup(str));
1819 i = str_set.insert(i, str_vec.back());
1824 DLLLOCAL
void addFile(
const char*& file) {
1825 file = addString(file);
1826 printd(5,
"qore_program_private::addFile('%s')\n", file);
1827 addStatementToIndexIntern(&statementByFileIndex, file,
nullptr, -1,
nullptr, -1);
1830 DLLLOCAL
void addFile(
const char*& file,
const char*& source,
int offset) {
1831 file = addString(file);
1833 source = addString(source);
1835 printd(5,
"qore_program_private::addFile('%s', '%s', %d)\n", file, source ? source :
"(null)", offset);
1836 addStatementToIndexIntern(&statementByFileIndex, file,
nullptr, -1, source, offset);
1838 addStatementToIndexIntern(&statementByLabelIndex, source,
nullptr, -1, file, offset);
1842 DLLLOCAL
void addUserFeature(
const char* f) {
1844 assert(!userFeatureList.find(f));
1845 userFeatureList.push_back(f);
1848 DLLLOCAL
void removeUserFeature(
const char* f) {
1849 CharPtrList::iterator i = userFeatureList.safe_dslist<std::string>::find(f);
1850 assert(i != userFeatureList.end());
1851 userFeatureList.erase(i);
1854 DLLLOCAL
void addFeature(
const char* f) {
1855 assert(!featureList.find(f));
1856 featureList.push_back(f);
1859 DLLLOCAL
void removeFeature(
const char* f) {
1860 CharPtrList::iterator i = featureList.safe_dslist<std::string>::find(f);
1861 assert(i != featureList.end());
1862 featureList.erase(i);
1865 DLLLOCAL
void runtimeImportSystemClassesIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1866 DLLLOCAL
void runtimeImportSystemConstantsIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1867 DLLLOCAL
void runtimeImportSystemFunctionsIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1868 DLLLOCAL
void runtimeImportSystemHashDeclsIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1870 DLLLOCAL
void runtimeImportSystemClasses(
ExceptionSink* xsink);
1871 DLLLOCAL
void runtimeImportSystemConstants(
ExceptionSink* xsink);
1872 DLLLOCAL
void runtimeImportSystemFunctions(
ExceptionSink* xsink);
1873 DLLLOCAL
void runtimeImportSystemHashDecls(
ExceptionSink* xsink);
1882 assert(extmap.find(owner) == extmap.end());
1883 extmap.insert(extmap_t::value_type(owner, pud));
1888 extmap_t::const_iterator i = extmap.find(owner);
1889 return i == extmap.end() ? nullptr : i->second;
1893 return qore_root_ns_private::getGlobalVars(*RootNS);
1896 DLLLOCAL LocalVar* createLocalVar(
const char* name,
const QoreTypeInfo* typeInfo);
1898 DLLLOCAL
const AbstractQoreFunctionVariant* runtimeFindCall(
const char* name,
const QoreListNode* params,
ExceptionSink* xsink);
1903 return pgm.priv->runtimeFindClass(class_name, xsink);
1907 pgm.priv->doThreadInit(xsink);
1912 if (!pgm.priv->exec_class) {
1913 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>))");
1916 pgm.priv->exec_class_rv.discard(xsink);
1917 pgm.priv->exec_class_rv = rv.release();
1923 return pgm.priv->preregisterNewThread(xsink);
1927 DLLLOCAL
static void cancelPreregistration(
QoreProgram& pgm) {
1928 pgm.priv->cancelPreregistration();
1932 DLLLOCAL
static void registerNewThread(
QoreProgram& pgm,
int tid) {
1933 pgm.priv->registerNewThread(tid);
1937 pgm.priv->runtimeImportSystemClasses(xsink);
1941 pgm.priv->runtimeImportSystemHashDecls(xsink);
1945 pgm.priv->runtimeImportSystemConstants(xsink);
1949 pgm.priv->runtimeImportSystemFunctions(xsink);
1953 pgm.priv->runtimeImportSystemApi(xsink);
1956 DLLLOCAL
static qore_program_private*
get(
QoreProgram& pgm) {
1961 pgm.priv->clearThreadData(xsink);
1964 DLLLOCAL
static void addUserFeature(
QoreProgram& pgm,
const char* f) {
1965 pgm.priv->addUserFeature(f);
1968 DLLLOCAL
static void addStatement(
QoreProgram& pgm, AbstractStatement* s) {
1969 pgm.priv->addStatement(s);
1972 DLLLOCAL
static const AbstractQoreZoneInfo* currentTZIntern(
QoreProgram& pgm) {
1973 return pgm.priv->TZ;
1977 return pgm.priv->lockParsing(xsink);
1980 DLLLOCAL
static void unlockParsing(
QoreProgram& pgm) {
1981 pgm.priv->unlockParsing();
1985 return pgm.priv->incThreadCount(xsink);
1988 DLLLOCAL
static void decThreadCount(
QoreProgram& pgm,
int tid) {
1989 pgm.priv->decThreadCount(tid);
1993 DLLLOCAL
static void addSignal(
QoreProgram& pgm,
int sig) {
1994 assert(pgm.priv->sigset.find(sig) == pgm.priv->sigset.end());
1995 pgm.priv->sigset.insert(sig);
1999 DLLLOCAL
static void delSignal(
QoreProgram& pgm,
int sig) {
2000 assert(pgm.priv->sigset.find(sig) != pgm.priv->sigset.end());
2001 pgm.priv->sigset.erase(sig);
2005 pgm.priv->qore_program_private_base::startThread(xsink);
2009 return pgm.priv->setThreadInit(n_thr_init, xsink);
2013 return pgm->priv->runtimeGetCallReference(name, xsink);
2016 DLLLOCAL
static const ParseWarnOptions& getParseWarnOptions(
const QoreProgram* pgm) {
2017 return pgm->priv->pwo;
2020 DLLLOCAL
static bool setSaveParseWarnOptions(
const QoreProgram* pgm,
const ParseWarnOptions &new_opts, ParseWarnOptions &old_opts) {
2021 if (new_opts == pgm->priv->pwo)
2023 old_opts = pgm->priv->pwo;
2024 pgm->priv->pwo = new_opts;
2028 DLLLOCAL
static void setParseWarnOptions(
const QoreProgram* pgm,
const ParseWarnOptions &new_opts) {
2029 pgm->priv->pwo = new_opts;
2032 DLLLOCAL
static bool setThreadVarData(
QoreProgram* pgm, ThreadProgramData* td, ThreadLocalProgramData* &tlpd,
bool run) {
2033 return pgm->priv->setThreadVarData(td, tlpd, run);
2036 DLLLOCAL
static void finalizeThreadData(
QoreProgram* pgm, ThreadProgramData* td,
arg_vec_t*& cl) {
2037 pgm->priv->finalizeThreadData(td, cl);
2041 return pgm->priv->endThread(td, xsink);
2045 pgm->priv->makeParseException(loc,
"PARSE-EXCEPTION", desc);
2048 DLLLOCAL
static void makeParseException(
QoreProgram* pgm,
const QoreProgramLocation &loc,
const char* err,
QoreStringNode* desc) {
2049 pgm->priv->makeParseException(loc, err, desc);
2054 return pgm->priv->getDefine(name, is_defined);
2057 DLLLOCAL
static const QoreValue parseGetDefine(
QoreProgram* pgm,
const char* name,
bool& is_defined) {
2058 return pgm->priv->getDefine(name, is_defined);
2063 return pgm->priv->runTimeGetDefine(name, is_defined);
2066 DLLLOCAL
static QoreValue runTimeGetDefine(
QoreProgram* pgm,
const char* name,
bool& is_defined) {
2067 return pgm->priv->runTimeGetDefine(name, is_defined);
2071 return pgm->priv->runTimeGetAllDefines();
2074 DLLLOCAL
static bool parseUnDefine(
QoreProgram* pgm,
const char* name) {
2075 return pgm->priv->parseUnDefine(name);
2079 return pgm->priv->runTimeUnDefine(name, xsink);
2082 DLLLOCAL
static bool parseIsDefined(
QoreProgram* pgm,
const char* name) {
2083 return pgm->priv->isDefined(name);
2086 DLLLOCAL
static bool runTimeIsDefined(
QoreProgram* pgm,
const char* name) {
2087 return pgm->priv->runTimeIsDefined(name);
2090 DLLLOCAL
static void parseDefine(
QoreProgram* pgm,
const QoreProgramLocation* loc,
const char* str,
QoreValue val) {
2091 pgm->priv->parseDefine(loc, str, val);
2095 pgm->priv->runTimeDefine(str, val, xsink);
2098 DLLLOCAL
static void addParseException(
QoreProgram* pgm,
ExceptionSink* xsink,
const QoreProgramLocation* loc =
nullptr) {
2100 pgm->priv->addParseException(*xsink, loc);
2104 DLLLOCAL
static void addParseException(
QoreProgram* pgm,
ExceptionSink& xsink,
const QoreProgramLocation* loc =
nullptr) {
2105 pgm->priv->addParseException(xsink, loc);
2108 DLLLOCAL
static void exportFunction(
QoreProgram* srcpgm,
ExceptionSink* xsink,
QoreProgram* trgpgm,
const char* name,
const char* new_name =
nullptr,
bool inject =
false) {
2109 srcpgm->priv->exportFunction(xsink, trgpgm->priv, name, new_name, inject);
2113 return pgm->priv->parseAddDomain(n_dom);
2117 return pgm.priv->dom;
2121 pgm.priv->dom |= n_dom;
2125 int64 rv = pgm.priv->pwo.parse_options;
2126 pgm.priv->pwo.parse_options = po;
2130 DLLLOCAL
static void makeParseWarning(
QoreProgram* pgm,
const QoreProgramLocation &loc,
int code,
const char* warn,
const char* fmt, ...) {
2132 if (!pgm->priv->warnSink || !(code & pgm->priv->pwo.warn_mask))
2138 va_start(args, fmt);
2139 int rc = desc->
vsprintf(fmt, args);
2144 QoreException *ne =
new ParseException(loc, warn, desc);
2145 pgm->priv->warnSink->raiseException(ne);
2148 DLLLOCAL
static void makeParseWarning(
QoreProgram* pgm,
const QoreProgramLocation &loc,
int code,
const char* warn,
QoreStringNode* desc) {
2150 if (!pgm->priv->warnSink || !(code & pgm->priv->pwo.warn_mask)) {
2155 QoreException *ne =
new ParseException(loc, warn, desc);
2156 pgm->priv->warnSink->raiseException(ne);
2160 pgm->priv->exportGlobalVariable(name, readonly, *(tpgm->priv), xsink);
2163 DLLLOCAL
void attachDebug(
const qore_debug_program_private* n_dpgm) {
2164 printd(5,
"qore_program_private::attachDebug(n_dpgm: %p), dpgm: %p\n", n_dpgm, dpgm);
2170 dpgm =
const_cast<qore_debug_program_private*
>(n_dpgm);
2171 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());
2172 for (
auto& i : pgm_data_map) {
2173 i.second->dbgPendingAttach();
2174 i.second->dbgBreak();
2178 DLLLOCAL
void detachDebug(
const qore_debug_program_private* n_dpgm) {
2179 printd(5,
"qore_program_private::detachDebug(n_dpgm: %p), dpgm: %p\n", n_dpgm, dpgm);
2182 assert(n_dpgm==dpgm);
2186 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());
2187 for (
auto& i : pgm_data_map) {
2188 i.second->dbgPendingDetach();
2193 DLLLOCAL
void onAttach(DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2194 DLLLOCAL
void onDetach(DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2195 DLLLOCAL
void onStep(
const StatementBlock *blockStatement,
const AbstractStatement *statement,
unsigned bkptId,
int &flow, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2196 DLLLOCAL
void onFunctionEnter(
const StatementBlock *statement, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2197 DLLLOCAL
void onFunctionExit(
const StatementBlock *statement,
QoreValue& returnValue, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2198 DLLLOCAL
void onException(
const AbstractStatement *statement, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2199 DLLLOCAL
void onExit(
const StatementBlock *statement,
QoreValue& returnValue, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2201 DLLLOCAL
int breakProgramThread(
int tid) {
2202 printd(5,
"qore_program_private::breakProgramThread(), this: %p, tid: %d\n",
this,
gettid());
2204 for (
auto& i : pgm_data_map) {
2205 if (i.first->gettid() == tid) {
2206 i.second->dbgBreak();
2213 DLLLOCAL
void breakProgram() {
2214 printd(5,
"qore_program_private::breakProgram(), this: %p\n",
this);
2216 for (
auto& i : pgm_data_map) {
2217 i.second->dbgBreak();
2222 if (!bkpt ||
this == bkpt->pgm)
return;
2223 if (!checkAllowDebugging(xsink))
2229 breakpointList.push_back(bkpt);
2234 DLLLOCAL
void deleteAllBreakpoints() {
2236 for (QoreBreakpointList_t::iterator it = breakpointList.begin(); it != breakpointList.end(); ++it) {
2237 (*it)->unassignAllStatements();
2238 (*it)->pgm =
nullptr;
2241 breakpointList.clear();
2244 DLLLOCAL
void getBreakpoints(QoreBreakpointList_t &bkptList) {
2247 for (QoreBreakpointList_t::iterator it = breakpointList.begin(); it != breakpointList.end(); ++it) {
2248 bkptList.push_back(*it);
2253 DLLLOCAL
void getStatementBreakpoints(
const AbstractStatement* statement, QoreBreakpointList_t &bkptList) {
2256 if (statement->breakpoints) {
2257 for (std::list<QoreBreakpoint*>::iterator it = statement->breakpoints->begin(); it != statement->breakpoints->end(); ++it) {
2258 bkptList.push_back(*it);
2264 DLLLOCAL
inline unsigned onCheckBreakpoint(
const AbstractStatement *statement,
ExceptionSink* xsink) {
2274 DLLLOCAL
unsigned long getStatementId(
const AbstractStatement* statement)
const {
2278 ReverseStatementIdMap_t::const_iterator i = reverseStatementIds.find((AbstractStatement*) statement);
2279 if (i == reverseStatementIds.end())
2286 if (statementId == 0 || statementId > statementIds.size())
2288 return statementIds[statementId-1];
2291 DLLLOCAL
unsigned getProgramId()
const {
2304 qore_root_ns_private::clearData(*RootNS, xsink);
2307 DLLLOCAL
static QoreProgram* resolveProgramId(
unsigned programId) {
2308 printd(5,
"qore_program_private::resolveProgramId(%x)\n", programId);
2310 for (qore_program_to_object_map_t::iterator i = qore_program_to_object_map.begin(); i != qore_program_to_object_map.end(); i++) {
2311 if (i->first->priv->programId == programId)
2320 xsink->
raiseException(
"DEBUGGING",
"program does not provide internal data for debugging");
2328 DLLLOCAL
void addStatementToIndexIntern(name_section_sline_statement_map_t* statementIndex,
const char* key, AbstractStatement *statement,
int offs,
const char* section,
int sectionOffs);
2329 DLLLOCAL
static void registerStatement(
QoreProgram *pgm, AbstractStatement *statement,
bool addToIndex);
2330 DLLLOCAL
QoreHashNode* getSourceIndicesIntern(name_section_sline_statement_map_t* statementIndex,
ExceptionSink* xsink)
const;
2332 return getSourceIndicesIntern(&statementByLabelIndex, xsink);
2335 return getSourceIndicesIntern(&statementByFileIndex, xsink);
2338 DLLLOCAL AbstractStatement* getStatementFromIndex(
const char* name,
int line) {
2339 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d), this: %p, file#: %d, label#: %d\n", name, line,
this, statementByFileIndex.size(), statementByLabelIndex.size());
2341 name_section_sline_statement_map_t::iterator it;
2342 if (statementByFileIndex.empty()) {
2345 bool addOffs =
true;
2346 if (!name || *name ==
'\0') {
2347 if (statementByFileIndex.size() != 1)
2349 it = statementByFileIndex.begin();
2351 size_t l = strlen(name);
2352 it = statementByFileIndex.find(name);
2353 if (it == statementByFileIndex.end()) {
2354 it = statementByLabelIndex.find(name);
2355 if (it == statementByLabelIndex.end()) {
2358 it = statementByFileIndex.begin();
2359 while (it != statementByFileIndex.end()) {
2360 size_t k = strlen(it->first);
2362 if (strcmp(name, it->first + k - l) == 0) {
2364 if (k == l || name[0] ==
'/' || it->first[k-l-1] ==
'/') {
2371 if (it == statementByFileIndex.end()) {
2372 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) no suffix match, this: %p\n", name, line,
this);
2375 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found by file suffix match, this: %p\n", name, line,
this);
2378 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found by label full match, this: %p\n", name, line,
this);
2381 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found by file full match, this: %p\n", name, line,
this);
2384 sline_statement_map_t *ssm = &it->second->statementMap;
2385 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found '%s', this: %p, ssm#: %d\n", name, line, it->first,
this, ssm->size());
2386 if (ssm->size() == 0)
2389 sline_statement_map_t::iterator li = ssm->upper_bound(line);
2390 if (li == ssm->begin()) {
2391 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) no statement found by line #1, this: %p\n", name, line,
this);
2397 AbstractStatement* st =
nullptr;
2400 if (ln != li->first) {
2404 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) {
2405 int n = li->second->loc->end_line - li->second->loc->start_line;
2418 if (li == ssm->begin())
2423 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);
2425 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) no statement found by line #2, this: %p\n", name, line,
this);
2431 printd(5,
"qore_program_private::registerQoreObject() pgm: %p, pgmid: %d\n", pgm, getProgramId());
2433 qore_program_to_object_map_t::iterator i = qore_program_private::qore_program_to_object_map.find(pgm);
2434 assert(i != qore_program_private::qore_program_to_object_map.end());
2435 if (i->second && i->second != o) {
2436 xsink->
raiseException(
"PROGRAM-ERROR",
"The Program has already assigned QoreObject");
2443 printd(5,
"qore_program_private::unregisterQoreObject() pgm: %p, pgmid: %d\n", pgm, getProgramId());
2445 qore_program_to_object_map_t::iterator i = qore_program_private::qore_program_to_object_map.find(pgm);
2446 assert(i != qore_program_private::qore_program_to_object_map.end());
2447 assert(i->second == o);
2448 i->second =
nullptr;
2453 qore_program_to_object_map_t::iterator i = qore_program_to_object_map.find(pgm);
2454 if (i == qore_program_to_object_map.end()) {
2463 qore_program_to_object_map_t::iterator i = qore_program_to_object_map.find(pgm);
2464 assert(i != qore_program_to_object_map.end());
2466 printd(5,
"qore_program_private::getQoreObject() pgm: %p, pgmid: %d, second: %p\n", i->first, i->first->getProgramId(), i->second);
2470 printd(5,
"qore_program_private::getQoreObject() pgm: %p, pgmid: %d, new second: %p\n", pgm, pgm->
getProgramId(), i->second);
2480 qore_program_to_object_map_t::iterator i = qore_program_to_object_map.begin();
2481 while (i != qore_program_to_object_map.end()) {
2483 printd(5,
"qore_program_private::getAllQoreObjects() pgm: %p, pgmid: %d, second: %p\n", i->first, i->first->getProgramId(), i->second);
2487 printd(5,
"qore_program_private::getAllQoreObjects() pgm: %p, pgmid: %d, new second: %p\n", i->first, i->first->getProgramId(), i->second);
2490 (*l)->push(i->second,
nullptr);
2497 class ParseWarnHelper :
public ParseWarnOptions {
2501 DLLLOCAL ParseWarnHelper(
const ParseWarnOptions &new_opts) {
2503 restore = pgm ? qore_program_private::setSaveParseWarnOptions(pgm, new_opts, *
this) : false;
2505 DLLLOCAL ~ParseWarnHelper() {
2507 qore_program_private::setParseWarnOptions(
getProgram(), *
this);
2511 typedef std::map<QoreProgram*, qore_program_private*> qore_program_map_t;
2514 class qore_debug_program_private {
2519 qore_program_map_t qore_program_map;
2522 DLLLOCAL qore_debug_program_private(
QoreDebugProgram *n_dpgm): dpgm(n_dpgm) {};
2523 DLLLOCAL ~qore_debug_program_private() {
2524 assert(qore_program_map.empty());
2528 if (!pgm->priv->checkAllowDebugging(xsink))
2531 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2532 printd(5,
"qore_debug_program_private::addProgram(), this: %p, pgm: %p, i: %p, end: %p\n",
this, pgm, i, qore_program_map.end());
2533 if (i != qore_program_map.end())
2535 qore_program_map.insert(qore_program_map_t::value_type(pgm, pgm->priv));
2537 pgm->priv->attachDebug(
this);
2542 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2543 printd(5,
"qore_debug_program_private::removeProgram(), this: %p, pgm: %p, i: %p, end: %p\n",
this, pgm, i, qore_program_map.end());
2544 if (i == qore_program_map.end())
2546 pgm->priv->detachDebug(
this);
2547 qore_program_map.erase(i);
2552 DLLLOCAL
void removeAllPrograms() {
2554 printd(5,
"qore_debug_program_private::removeAllPrograms(), this: %p\n",
this);
2555 qore_program_map_t::iterator i;
2556 while ((i = qore_program_map.begin()) != qore_program_map.end()) {
2557 qore_program_private* qpp = i->second;
2559 qore_program_map.erase(i);
2560 qpp->detachDebug(
this);
2567 printd(5,
"qore_debug_program_private::getAllProgramObjects(), this: %p\n",
this);
2569 qore_program_map_t::iterator i = qore_program_map.begin();
2570 while (i != qore_program_map.end()) {
2573 (*l)->push(o,
nullptr);
2580 DLLLOCAL
void onAttach(
QoreProgram *pgm, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2581 AutoQoreCounterDec ad(&debug_program_counter);
2582 dpgm->onAttach(pgm, rs, rts, xsink);
2584 DLLLOCAL
void onDetach(
QoreProgram *pgm, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2585 AutoQoreCounterDec ad(&debug_program_counter);
2586 dpgm->onDetach(pgm, rs, rts, xsink);
2594 DLLLOCAL
void onStep(
QoreProgram *pgm,
const StatementBlock *blockStatement,
const AbstractStatement *statement,
unsigned bkptId,
int &flow, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2595 AutoQoreCounterDec ad(&debug_program_counter);
2596 dpgm->
onStep(pgm, blockStatement, statement, bkptId, flow, rs, rts, xsink);
2599 DLLLOCAL
void onFunctionEnter(
QoreProgram *pgm,
const StatementBlock *statement, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2600 AutoQoreCounterDec ad(&debug_program_counter);
2606 DLLLOCAL
void onFunctionExit(
QoreProgram *pgm,
const StatementBlock *statement,
QoreValue& returnValue, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2607 AutoQoreCounterDec ad(&debug_program_counter);
2608 dpgm->
onFunctionExit(pgm, statement, returnValue, rs, rts, xsink);
2613 DLLLOCAL
void onException(
QoreProgram* pgm,
const AbstractStatement* statement, DebugRunStateEnum& rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2614 AutoQoreCounterDec ad(&debug_program_counter);
2615 dpgm->
onException(pgm, statement, rs, rts, xsink);
2620 DLLLOCAL
void onExit(
QoreProgram *pgm,
const StatementBlock *statement,
QoreValue& returnValue, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2621 AutoQoreCounterDec ad(&debug_program_counter);
2622 dpgm->
onExit(pgm, statement, returnValue, rs, rts, xsink);
2625 DLLLOCAL
int breakProgramThread(
QoreProgram* pgm,
int tid) {
2632 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2633 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);
2634 if (i == qore_program_map.end())
2636 if (i->second->breakProgramThread(tid))
2648 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2649 printd(5,
"qore_debug_program_private::breakProgram(), this: %p, pgm: %p, i: %p, end: %p\n",
this, pgm, i, qore_program_map.end());
2650 if (i == qore_program_map.end())
2652 i->second->breakProgram();
2656 DLLLOCAL
void waitForTerminationAndClear(
ExceptionSink* xsink) {
2657 removeAllPrograms();
2662 DLLLOCAL
int getInterruptedCount() {
2663 return debug_program_counter.
getCount();
DLLEXPORT const char * c_str() const
returns the string's buffer; this data should not be changed
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...
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:130
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:239
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:1027
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:133
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:1104
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