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 =
nullptr,
int offset = 0) {
66 thread_set_class_and_ns(
nullptr,
nullptr, cls, ns);
67 beginParsing(file,
nullptr, src, offset);
70 DLLLOCAL ~QoreParseLocationHelper() {
72 thread_set_class_and_ns(cls, ns);
77 const qore_class_private* cls;
82 typedef safe_dslist<LocalVar*> local_var_list_t;
85 typedef StatementBlock* q_exp_t;
87 class LocalVariableList :
public local_var_list_t {
89 DLLLOCAL LocalVariableList() {
92 DLLLOCAL ~LocalVariableList() {
93 for (local_var_list_t::iterator i = begin(), e = end(); i != e; ++i) {
101 #include "qore/intern/ThreadLocalVariableData.h"
102 #include "qore/intern/ThreadClosureVariableStack.h"
104 hashdecl ThreadLocalProgramData {
107 DLLLOCAL ThreadLocalProgramData(
const ThreadLocalProgramData& old) =
delete;
110 DebugRunStateEnum runState = DBG_RS_DETACH;
112 const AbstractStatement* runToStatement =
nullptr;
114 int functionCallLevel = 0;
116 DLLLOCAL
inline void setRunState(DebugRunStateEnum rs,
const AbstractStatement* rts) {
117 assert(rs < DBG_RS_STOPPED);
118 if (rs == DBG_RS_UNTIL_RETURN) {
119 functionCallLevel = 1;
121 printd(5,
"ThreadLocalProgramData::setRunState(), this: %p, rs: %d->%d, rts: %p\n",
this, runState, rs, rts);
123 runToStatement = rts;
126 volatile bool breakFlag =
false;
128 DLLLOCAL
inline void checkBreakFlag() {
129 if (breakFlag && runState != DBG_RS_DETACH) {
131 if (runState != DBG_RS_STOPPED) {
132 runState = DBG_RS_STEP;
134 printd(5,
"ThreadLocalProgramData::checkBreakFlag(), this: %p, rs: %d\n",
this, runState);
140 if (runState != DBG_RS_STOPPED) {
141 if (attachFlag > 0) {
146 }
else if (attachFlag < 0) {
155 ThreadLocalVariableData lvstack;
157 ThreadClosureVariableStack cvstack;
159 const AbstractQoreZoneInfo* tz =
nullptr;
166 DLLLOCAL ThreadLocalProgramData() : tz_set(false), inst(false) {
167 printd(5,
"ThreadLocalProgramData::ThreadLocalProgramData() this: %p\n",
this);
170 DLLLOCAL ~ThreadLocalProgramData() {
171 printd(5,
"ThreadLocalProgramData::~ThreadLocalProgramData() this: %p, rs: %d\n",
this, runState);
172 assert(lvstack.empty());
173 assert(cvstack.empty());
177 lvstack.finalize(sdh);
178 cvstack.finalize(sdh);
187 DLLLOCAL
void setTZ(
const AbstractQoreZoneInfo* n_tz) {
192 DLLLOCAL
void clearTZ() {
230 DLLLOCAL
int dbgStep(
const StatementBlock* blockStatement,
const AbstractStatement* statement,
ExceptionSink* xsink);
234 DLLLOCAL
void dbgFunctionEnter(
const StatementBlock* statement,
ExceptionSink* xsink);
238 DLLLOCAL
void dbgFunctionExit(
const StatementBlock* statement,
QoreValue& returnValue,
ExceptionSink* xsink);
242 DLLLOCAL
void dbgException(
const AbstractStatement* statement,
ExceptionSink* xsink);
251 DLLLOCAL
void dbgBreak() {
252 printd(5,
"ThreadLocalProgramData::dbgBreak(), this: %p\n",
this);
258 DLLLOCAL
void dbgPendingAttach() {
259 printd(5,
"ThreadLocalProgramData::dbgPendingAttach(), this: %p\n",
this);
265 DLLLOCAL
void dbgPendingDetach() {
266 printd(5,
"ThreadLocalProgramData::dbgPendingDetach(), this: %p\n",
this);
273 DLLLOCAL
bool dbgIsAttached() {
274 return runState != DBG_RS_DETACH;
279 typedef vector_map_t<ThreadProgramData*, ThreadLocalProgramData*> pgm_data_map_t;
283 typedef vector_map_t<std::string, QoreValue> dmap_t;
287 typedef vector_map_t<const char*, int64> ppo_t;
290 class AbstractQoreZoneInfo;
294 DLLLOCAL
bool operator()(
const QoreProgramLocation* p1,
const QoreProgramLocation* p2)
const {
302 hashdecl pgmloc_vec_t :
public std::vector<QoreProgramLocation*> {
303 DLLLOCAL ~pgmloc_vec_t() {
307 DLLLOCAL
void clear() {
308 for (
auto& i : *
this) {
312 std::vector<QoreProgramLocation*>::clear();
316 class qore_program_private_base {
317 friend class QoreProgramAccessHelper;
320 DLLLOCAL
void setDefines();
322 typedef vector_map_t<const char*, AbstractQoreProgramExternalData*> extmap_t;
327 LocalVariableList local_var_list;
332 unsigned thread_count;
333 unsigned thread_waiting;
334 unsigned parse_count = 0;
344 typedef std::set<const char*, ltstr> str_set_t;
348 typedef std::set<const QoreProgramLocation*, ltpgm> loc_set_t;
351 typedef std::set<std::string> strset_t;
353 strset_t featureList;
356 strset_t userFeatureList;
371 TopLevelStatementBlock sb;
374 bool only_first_except : 1,
376 po_allow_restrict : 1,
379 requires_exception : 1,
381 parsing_in_progress : 1,
387 typedef std::set<q_exp_t> q_exp_set_t;
389 q_exp_t new_expression =
nullptr;
393 int exceptions_raised,
396 ParseWarnOptions pwo;
401 std::string exec_class_name, script_dir, script_path, script_name, include_path;
408 mutable unsigned twaiting;
411 pgm_data_map_t pgm_data_map;
414 const AbstractQoreZoneInfo* TZ;
432 : thread_count(0), thread_waiting(0), plock(&ma_recursive), parseSink(nullptr), warnSink(nullptr),
433 pendingParseSink(nullptr), RootNS(nullptr), QoreNS(nullptr),
435 only_first_except(false), po_locked(false), po_allow_restrict(true), exec_class(false), base_object(false),
436 requires_exception(false),
438 parsing_in_progress(false),
441 expression_mode(false),
443 exceptions_raised(0), ptid(0), pwo(n_parse_options), dom(0), pend_dom(0), thread_local_storage(nullptr), twaiting(0),
444 thr_init(nullptr), pgm(n_pgm) {
445 printd(QPP_DBG_LVL,
"qore_program_private_base::qore_program_private_base() this: %p pgm: %p po: " QLLD
"\n",
this, pgm, n_parse_options);
448 pgm->priv = (qore_program_private*)
this;
451 setParent(p_pgm, n_parse_options);
453 TZ = QTZM.getLocalZoneInfo();
458 Var *var = qore_root_ns_private::runtimeCreateVar(*RootNS, *QoreNS,
"ARGV", listTypeInfo,
true);
460 var->setInitial(ARGV->
copy());
462 var = qore_root_ns_private::runtimeCreateVar(*RootNS, *QoreNS,
"QORE_ARGV", listTypeInfo,
true);
463 if (var && QORE_ARGV)
464 var->setInitial(QORE_ARGV->
copy());
466 var = qore_root_ns_private::runtimeCreateVar(*RootNS, *QoreNS,
"ENV", hashTypeInfo,
true);
468 var->setInitial(ENV->
copy());
473 DLLLOCAL ~qore_program_private_base() {
474 printd(QPP_DBG_LVL,
"qore_program_private_base::~qore_program_private_base() this: %p pgm: %p\n",
this, pgm);
478 DLLLOCAL
const QoreProgramLocation* getLocation(
int sline,
int eline);
479 DLLLOCAL
const QoreProgramLocation* getLocation(
const QoreProgramLocation&,
int sline,
int eline);
487 DLLLOCAL
void newProgram();
490 class PreParseHelper {
492 qore_program_private_base *p;
496 DLLLOCAL PreParseHelper(qore_program_private_base *n_p) : p(n_p), swapped(false) {
498 if (!p->pendingParseSink)
500 p->parseSink = p->pendingParseSink;
505 DLLLOCAL ~PreParseHelper() {
507 p->parseSink =
nullptr;
511 class qore_debug_program_private;
513 class AutoQoreCounterDec {
517 AutoQoreCounterDec() {}
519 AutoQoreCounterDec(
QoreCounter* n_cnt,
bool incNow =
true): cnt(n_cnt), incFlag(false) {
524 ~AutoQoreCounterDec() {
536 class qore_program_private :
public qore_program_private_base {
539 DLLLOCAL
void init(
QoreProgram* n_pgm,
int64 n_parse_options,
const AbstractQoreZoneInfo* n_TZ = QTZM.getLocalZoneInfo()) {
547 if (!pendingParseSink)
553 qore_debug_program_private* dpgm;
555 QoreBreakpointList_t breakpointList;
558 typedef std::map<int, AbstractStatement*> sline_statement_map_t;
560 typedef std::map<const char*, int, ltstr> section_offset_map_t;
562 hashdecl section_sline_statement_map {
563 section_offset_map_t sectionMap;
564 sline_statement_map_t statementMap;
567 typedef section_sline_statement_map section_sline_statement_map_t;
570 typedef vector_map_t<const char*, section_sline_statement_map_t*> name_section_sline_statement_map_t;
574 name_section_sline_statement_map_t statementByFileIndex;
575 name_section_sline_statement_map_t statementByLabelIndex;
578 typedef std::vector<AbstractStatement*> StatementVector_t;
579 StatementVector_t statementIds;
582 typedef std::map<AbstractStatement*, unsigned long> ReverseStatementIdMap_t;
583 ReverseStatementIdMap_t reverseStatementIds;
590 DLLLOCAL qore_debug_program_private* getDebugProgram(AutoQoreCounterDec& ad) {
593 qore_debug_program_private* ret = dpgm;
602 DLLLOCAL
bool isBreakpointRegistered(
const QoreBreakpoint *bkpt)
const {
603 return std::find(breakpointList.begin(), breakpointList.end(), bkpt) != breakpointList.end();
607 typedef std::map<QoreProgram*, QoreObject*> qore_program_to_object_map_t;
608 static qore_program_to_object_map_t qore_program_to_object_map;
610 static volatile unsigned programIdCounter;
616 DLLLOCAL ~qore_program_private();
618 DLLLOCAL
void depRef() {
623 DLLLOCAL
void depDeref() {
640 for (
auto& i : pgm_data_map) {
641 i.second->finalize(sdh);
647 for (
auto& i : pgm_data_map) {
648 i.second->del(xsink);
649 i.first->delProgram(pgm);
653 DLLLOCAL
void waitForTerminationAndClear(
ExceptionSink* xsink);
665 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed has already been deleted and therefore no new threads can be started in it");
674 DLLLOCAL
void cancelPreregistration() {
678 assert(thread_count > 0);
679 if (!--thread_count && thread_waiting)
684 DLLLOCAL
void registerNewThread(
int tid) {
688 assert(thread_count);
709 if (ptid && ptid != tid) {
710 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed has already been deleted and therefore cannot be accessed at runtime");
713 if (parsing_in_progress) {
714 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed is currently undergoing parsing and cannot be accessed at runtime");
723 DLLLOCAL
void incThreadCount() {
729 if (ptid && ptid != tid) {
730 throw QoreStandardException(
"PROGRAM-ERROR",
"the Program accessed has already been deleted and therefore cannot be accessed at runtime");
732 if (parsing_in_progress) {
733 throw QoreStandardException(
"PROGRAM-ERROR",
"the Program accessed is currently undergoing parsing and cannot be accessed at runtime");
740 DLLLOCAL
void decThreadCount(
int tid) {
744 ptid_map_t::iterator i = tidmap.find(tid);
745 assert(i != tidmap.end());
749 assert(thread_count > 0);
750 if (!--thread_count && thread_waiting)
759 for (
auto& i : tidmap) {
760 l.
push(i.first,
nullptr);
769 while (parse_tid != -1 && parse_tid != tid && !ptid) {
777 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed has already been deleted and " \
778 "therefore cannot be accessed");
789 DLLLOCAL
void unlockParsing() {
793 assert(parse_count > 0);
794 if (!(--parse_count)) {
796 if (thread_waiting) {
802 DLLLOCAL
bool parsingLocked()
const {
807 DLLLOCAL
void waitForAllThreadsToTerminateIntern() {
810 ptid_map_t::iterator i = tidmap.find(tid);
811 unsigned adj = (i != tidmap.end() ? 1 : 0);
813 while ((thread_count - adj) || parse_count) {
820 DLLLOCAL
void waitForAllThreadsToTerminate() {
823 waitForAllThreadsToTerminateIntern();
826 DLLLOCAL
const char* parseGetScriptPath()
const {
827 return script_path.empty() ? nullptr : script_path.c_str();
830 DLLLOCAL
const char* parseGetScriptDir()
const {
831 return script_dir.empty() ? nullptr : script_dir.c_str();
834 DLLLOCAL
const char* parseGetScriptName()
const {
835 return script_name.empty() ? nullptr : script_name.c_str();
841 return script_path.empty() ? nullptr :
new QoreStringNode(script_path);
847 return script_dir.empty() ? nullptr :
new QoreStringNode(script_dir);
853 return script_name.empty() ? nullptr :
new QoreStringNode(script_name);
856 DLLLOCAL
void setScriptPathExtern(
const char* path) {
862 DLLLOCAL
void setScriptPath(
const char* path) {
872 script_dir =
"." QORE_DIR_SEP_STR;
873 script_path = script_dir + script_name;
877 script_dir.assign(path, p - path);
892 for (
auto& i : featureList) {
902 DLLLOCAL
int internParsePending(
ExceptionSink* xsink,
const char* code,
const char* label,
903 const char* orig_src =
nullptr,
int offset = 0,
bool standard_parse =
true) {
907 assert(code && code[0]);
911 const char* sname = label;
912 const char* src = orig_src;
914 addFile(src, sname, offset);
922 QoreParseLocationHelper qplh(sname, src, offset);
925 beginParsing(sname,
nullptr, src, offset);
927 if (!parsing_in_progress) {
928 parsing_in_progress =
true;
937 yy_scan_string(code, lexer);
938 yyset_lineno(1, lexer);
942 printd(5,
"qore_program_private::internParsePending() returned from yyparse()\n");
946 if (standard_parse) {
947 printd(5,
"qore_program_private::internParsePending() parse exception: calling parseRollback()\n");
948 internParseRollback(xsink);
949 requires_exception =
false;
953 printd(5,
"qore_program_private::internParsePending() about to call yylex_destroy()\n");
954 yylex_destroy(lexer);
955 printd(5,
"qore_program_private::internParsePending() returned from yylex_destroy()\n");
964 if (pendingParseSink) {
966 pendingParseSink =
nullptr;
972 xsink->
raiseException(
"PARSE-ERROR",
"parsing can only happen once for each Program container");
978 DLLLOCAL
int parsePending(
const char* code,
const char* label,
ExceptionSink* xsink,
ExceptionSink* wS,
int wm,
const char* orig_src =
nullptr,
int offset = 0) {
981 ProgramRuntimeParseContextHelper pch(xsink, pgm);
987 if (checkParse(xsink)) {
991 startParsing(xsink, wS, wm);
993 int rc = internParsePending(xsink, code, label, orig_src, offset);
1002 DLLLOCAL
int internParseCommit(
bool standard_parse =
true);
1005 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1011 if (checkParse(xsink)) {
1015 startParsing(xsink, wS, wm);
1018 int rc = internParseCommit();
1021 parseSink =
nullptr;
1029 ProgramRuntimeParseContextHelper pch(xsink, pgm);
1035 internParseRollback(xsink);
1041 printd(5,
"QoreProgram::parse(fp: %p, name: %s, xsink: %p, wS: %p, wm: %d)\n", fp, name, xsink, wS, wm);
1047 printd(5,
"QoreProgram::parse(fp: %p, name: %s) EOF\n", fp, name);
1056 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1061 if (checkParse(xsink)) {
1065 startParsing(xsink, wS, wm);
1069 const char* sname = name;
1075 QoreParseLocationHelper qplh(sname);
1078 beginParsing(sname);
1080 if (!parsing_in_progress) {
1081 parsing_in_progress =
true;
1086 yyset_in(fp, lexer);
1091 internParseCommit();
1094 parseSink =
nullptr;
1100 yylex_destroy(lexer);
1101 if (only_first_except && exceptions_raised > 1)
1102 fprintf(stderr,
"\n%d exception(s) skipped\n\n", exceptions_raised);
1106 int wm,
const QoreString* source =
nullptr,
int offset = 0) {
1122 if (source && !source->empty() && !src.
set(source,
QCS_DEFAULT, xsink))
1125 parse(tstr->c_str(), tlstr->c_str(), xsink, wS, wm, source ? src->
c_str() :
nullptr, offset);
1129 const char* orig_src =
nullptr,
int offset = 0) {
1132 assert(code && code[0]);
1135 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1140 if (checkParse(xsink)) {
1144 startParsing(xsink, wS, wm);
1147 if (!internParsePending(xsink, code, label, orig_src, offset))
1148 internParseCommit();
1151 parseSink =
nullptr;
1160 xsink->
raiseException(
"EXPRESSION-ERROR",
"the expression cannot be empty");
1175 if (source && !source->empty() && !src.
set(source,
QCS_DEFAULT, xsink))
1178 return parseExpression(tstr->c_str(), tlstr->c_str(), xsink, wS, wm, source ? src->
c_str() :
nullptr, offset);
1181 DLLLOCAL q_exp_t parseExpression(
const char* code,
const char* label,
ExceptionSink* xsink,
ExceptionSink* wS,
int wm,
const char* orig_src =
nullptr,
int offset = 0) {
1184 assert(code && code[0]);
1187 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1192 assert(!expression_mode);
1193 assert(!new_expression);
1194 expression_mode =
true;
1196 QoreStringMaker exp_code(
"return (%s);", code);
1198 startParsing(xsink, wS, wm);
1201 if (!internParsePending(xsink, exp_code.c_str(), label, orig_src, offset,
false)) {
1202 internParseCommit(
false);
1204 parsing_in_progress =
false;
1208 parseSink =
nullptr;
1212 expression_mode =
false;
1213 q_exp_t rv = new_expression;
1214 if (new_expression) {
1216 exp_set.erase(new_expression);
1217 delete new_expression;
1220 new_expression =
nullptr;
1226 QORE_TRACE(
"QoreProgram::parseFile()");
1228 printd(5,
"QoreProgram::parseFile(%s)\n", filename);
1231 if (!(fp = fopen(filename,
"r"))) {
1232 if ((only_first_except && !exceptions_raised) || !only_first_except)
1233 xsink->
raiseErrnoException(
"PARSE-EXCEPTION", errno,
"cannot open qore script '%s'", filename);
1234 exceptions_raised++;
1237 ON_BLOCK_EXIT(fclose, fp);
1239 setScriptPath(filename);
1241 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1245 parse(fp, filename, xsink, wS, wm);
1249 assert(!str->
empty());
1263 if (source && !source->empty() && !src.
set(source,
QCS_DEFAULT, xsink))
1266 parsePending(tstr->getBuffer(), tlstr->getBuffer(), xsink, wS, wm, source ? src->
getBuffer() : 0, offset);
1270 DLLLOCAL
void importFunction(
ExceptionSink* xsink, QoreFunction *u,
const qore_ns_private& oldns,
const char* new_name =
nullptr,
bool inject =
false);
1278 thread_local_storage->
set(h);
1286 printd(5,
"QoreProgram::clearThreadData() this: %p h: %p (size: %d)\n",
this, h, h ? h->
size() : 0);
1296 thread_local_storage->
set(
nullptr);
1300 DLLLOCAL
void finalizeThreadData(ThreadProgramData* td,
SafeDerefHelper& sdh) {
1304 thread_local_storage->
set(
nullptr);
1312 pgm_data_map_t::iterator i = pgm_data_map.find(td);
1313 if (i != pgm_data_map.end()) {
1314 i->second->finalize(sdh);
1319 DLLLOCAL
int endThread(ThreadProgramData* td,
ExceptionSink* xsink) {
1320 ThreadLocalProgramData* tlpd =
nullptr;
1329 pgm_data_map_t::iterator i = pgm_data_map.find(td);
1330 if (i == pgm_data_map.end()) {
1334 pgm_data_map.erase(i);
1341 DLLLOCAL
void doTopLevelInstantiation(ThreadLocalProgramData& tlpd) {
1343 const LVList* lvl = sb.getLVList();
1345 for (
unsigned i = 0; i < lvl->size(); ++i) {
1346 lvl->lv[i]->instantiate();
1356 DLLLOCAL
bool setThreadVarData(ThreadProgramData* td, ThreadLocalProgramData*& new_tlpd,
bool run) {
1370 pgm_data_map_t::iterator i = pgm_data_map.find(td);
1371 if (i == pgm_data_map.end()) {
1374 ThreadLocalProgramData* tlpd =
new ThreadLocalProgramData;
1376 printd(5,
"qore_program_private::setThreadVarData() (first) this: %p pgm: %p td: %p run: %s inst: %s\n",
this, pgm, td, run ?
"true" :
"false", tlpd->inst ?
"true" :
"false");
1380 pgm_data_map.insert(pgm_data_map_t::value_type(td, tlpd));
1385 printd(5,
"qore_program_private::setThreadVarData() (first) this: %p pgm: %p td: %p\n",
this, pgm, td);
1386 doTopLevelInstantiation(*tlpd);
1392 ThreadLocalProgramData* tlpd = pgm_data_map[td];
1397 printd(5,
"qore_program_private::setThreadVarData() (not first) this: %p pgm: %p td: %p run: %s inst: %s\n",
this, pgm, td, run ?
"true" :
"false", tlpd->inst ?
"true" :
"false");
1399 if (run && !tlpd->inst) {
1400 doTopLevelInstantiation(*tlpd);
1406 DLLLOCAL
const AbstractQoreZoneInfo*
currentTZ(ThreadProgramData* tpd = get_thread_program_data())
const {
1408 pgm_data_map_t::const_iterator i = pgm_data_map.find(tpd);
1409 if (i != pgm_data_map.end() && i->second->tz_set)
1410 return i->second->tz;
1414 DLLLOCAL
void setTZ(
const AbstractQoreZoneInfo* n_TZ) {
1418 DLLLOCAL
void exportFunction(
ExceptionSink* xsink, qore_program_private* p,
const char* name,
const char* new_name =
nullptr,
bool inject =
false) {
1420 xsink->
raiseException(
"FUNCTION-IMPORT-ERROR",
"cannot import a function from the same Program object");
1425 xsink->
raiseException(
"FUNCTION-IMPORT-ERROR",
"cannot import function \"%s\" in a Program object without PO_ALLOW_INJECTION set", name);
1429 const QoreFunction* u;
1430 const qore_ns_private* ns =
nullptr;
1433 ProgramRuntimeParseAccessHelper rah(xsink, pgm);
1436 u = qore_root_ns_private::runtimeFindFunction(*RootNS, name, ns);
1440 xsink->
raiseException(
"PROGRAM-IMPORTFUNCTION-NO-FUNCTION",
"function '%s' does not exist in the current program scope", name);
1443 p->importFunction(xsink,
const_cast<QoreFunction*
>(u), *ns, new_name, inject);
1447 DLLLOCAL
bool parseExceptionRaised()
const {
1452 DLLLOCAL
void setParseOptionsIntern(
int64 po) {
1453 pwo.parse_options |= po;
1456 DLLLOCAL
void disableParseOptionsIntern(
int64 po) {
1457 pwo.parse_options &= ~po;
1460 DLLLOCAL
void replaceParseOptionsIntern(
int64 po) {
1461 pwo.parse_options = po;
1469 xsink->
raiseException(
"OPTIONS-LOCKED",
"parse options have been locked on this program object");
1473 setParseOptionsIntern(po);
1481 if (((po &
PO_FREE_OPTIONS) != po) && po_locked && !po_allow_restrict) {
1482 xsink->
raiseException(
"OPTIONS-LOCKED",
"parse options have been locked on this program object");
1486 disableParseOptionsIntern(po);
1493 xsink->
raiseException(
"OPTION-ERROR",
"the calling Program does not have the PO_NO_CHILD_PO_RESTRICTIONS option set, and therefore cannot call Program::replaceParseOptions()");
1498 replaceParseOptionsIntern(po);
1502 DLLLOCAL
int parseSetParseOptions(
const QoreProgramLocation* loc,
int64 po) {
1506 parse_error(*loc,
"parse options have been locked on this program object");
1510 setParseOptionsIntern(po);
1514 DLLLOCAL
int parseDisableParseOptions(
const QoreProgramLocation* loc,
int64 po) {
1517 if (((po &
PO_FREE_OPTIONS) != po) && po_locked && !po_allow_restrict) {
1518 parse_error(*loc,
"parse options have been locked on this program object");
1522 disableParseOptionsIntern(po);
1526 DLLLOCAL
void parseSetTimeZone(
const char* zone) {
1530 mergeParseException(xsink);
1534 const AbstractQoreZoneInfo *tz = (*zone ==
'-' || *zone ==
'+') ? QTZM.findCreateOffsetZone(zone, &xsink) : QTZM.findLoadRegion(zone, &xsink);
1537 mergeParseException(xsink);
1541 assert(tz || ((*zone ==
'-' || *zone ==
'+')));
1546 DLLLOCAL
void makeParseException(
const QoreProgramLocation& loc,
const char* err,
QoreStringNode* desc) {
1547 QORE_TRACE(
"QoreProgram::makeParseException()");
1550 if (!requires_exception) {
1551 if ((only_first_except && !exceptions_raised) || !only_first_except) {
1552 QoreException *ne =
new ParseException(loc, err, d.release());
1555 exceptions_raised++;
1559 DLLLOCAL
void parseException(QoreProgramLocation& loc,
const char* fmt, ...) {
1563 if (requires_exception)
1569 va_start(args, fmt);
1570 int rc = desc->
vsprintf(fmt, args);
1575 makeParseException(loc,
"PARSE-EXCEPTION", desc);
1581 dmap_t::iterator i = dmap.find(name);
1582 if (i != dmap.end()) {
1583 i->second.discard(xsink);
1593 DLLLOCAL
const QoreValue getDefine(
const char* name,
bool& is_defined) {
1594 dmap_t::iterator i = dmap.find(name);
1595 if (i != dmap.end()) {
1603 DLLLOCAL
QoreValue runTimeGetDefine(
const char* name,
bool& is_defined) {
1605 return getDefine(name, is_defined).refSelf();
1612 DLLLOCAL
bool unDefine(
const char* name,
ExceptionSink* xsink) {
1613 dmap_t::iterator i = dmap.find(name);
1614 if (i != dmap.end()) {
1615 i->second.discard(xsink);
1622 DLLLOCAL
bool parseUnDefine(
const char* name) {
1623 PreParseHelper pph(
this);
1624 return unDefine(name, parseSink);
1627 DLLLOCAL
bool runTimeUnDefine(
const char* name,
ExceptionSink* xsink) {
1629 return unDefine(name, xsink);
1633 DLLLOCAL
bool isDefined(
const char* name) {
1634 dmap_t::iterator i = dmap.find(name);
1635 return i == dmap.end() ? false :
true;
1638 DLLLOCAL
bool runTimeIsDefined(
const char* name) {
1640 return isDefined(name);
1643 DLLLOCAL
int checkDefine(
const QoreProgramLocation* loc,
const char* str,
ExceptionSink* xsink) {
1644 const char* p = str;
1646 xsink->
raiseException(*loc,
"PARSE-EXCEPTION", 0,
"illegal define variable '%s'; does not begin with an alphabetic character", p);
1651 if (!isalnum(*p) && *p !=
'_') {
1653 xsink->
raiseException(*loc,
"PARSE-EXCEPTION", 0,
"illegal character '%c' in define variable '%s'", *p, str);
1661 DLLLOCAL
void parseDefine(
const QoreProgramLocation* loc,
const char* str,
QoreValue val) {
1662 PreParseHelper pph(
this);
1664 if (checkDefine(loc, str, parseSink))
1667 setDefine(str, val, parseSink);
1671 const QoreProgramLocation* loc = get_runtime_location();
1673 if (checkDefine(loc, str, xsink))
1677 setDefine(str, val, xsink);
1682 ProgramRuntimeParseAccessHelper pah(xsink, pgm);
1685 return qore_root_ns_private::runtimeGetCallReference(*RootNS, name, xsink);
1688 DLLLOCAL
void pushParseOptions(
const char* pf) {
1690 ppo_t::iterator i = ppo.lower_bound(pf);
1691 if (i != ppo.end() && !strcmp(pf, i->first))
1693 ppo.insert(i, ppo_t::value_type(pf, pwo.parse_options));
1697 DLLLOCAL
void restoreParseOptions(
const char* pf) {
1698 ppo_t::iterator i = ppo.find(pf);
1699 if (i != ppo.end()) {
1701 pwo.parse_options = i->second;
1706 DLLLOCAL
void addParseException(
ExceptionSink& xsink,
const QoreProgramLocation* loc) {
1707 if (requires_exception) {
1714 xsink.overrideLocation(*loc);
1730 if ((pos & p_tmp) != pos) {
1731 rv = ((pos & p_tmp) ^ pos);
1736 if (neg && (neg & pwo.parse_options)) {
1737 rv |= (neg & pwo.parse_options);
1745 DLLLOCAL
void exportGlobalVariable(
const char* name,
bool readonly, qore_program_private& tpgm,
ExceptionSink* xsink);
1752 DLLLOCAL
void setThreadTZ(ThreadProgramData* tpd,
const AbstractQoreZoneInfo* tz) {
1754 pgm_data_map_t::iterator i = pgm_data_map.find(tpd);
1755 assert(i != pgm_data_map.end());
1756 i->second->setTZ(tz);
1759 DLLLOCAL
const AbstractQoreZoneInfo* getThreadTZ(ThreadProgramData* tpd,
bool& set)
const {
1761 pgm_data_map_t::const_iterator i = pgm_data_map.find(tpd);
1762 assert(i != pgm_data_map.end());
1763 set = i->second->tz_set;
1764 return i->second->tz;
1767 DLLLOCAL
void clearThreadTZ(ThreadProgramData* tpd) {
1769 pgm_data_map_t::iterator i = pgm_data_map.find(tpd);
1770 assert(i != pgm_data_map.end());
1771 i->second->clearTZ();
1774 DLLLOCAL
void addStatement(AbstractStatement* s);
1777 return parseExpression(source, label, xsink);
1781 ProgramThreadCountContextHelper pch(xsink, pgm,
true);
1785 if (exp_set.find(exp) == exp_set.end()) {
1786 xsink->
raiseException(
"INVALID-EXPRESSION",
"expression not registered to this Program object");
1789 ThreadFrameBoundaryHelper tfbh(
true);
1795 return rv.release();
1798 DLLLOCAL
void deleteExpression(q_exp_t exp) {
1800 q_exp_set_t::iterator i = exp_set.find(exp);
1801 if (i != exp_set.end()) {
1807 DLLLOCAL
void importClass(
ExceptionSink* xsink, qore_program_private& from_pgm,
const char* path,
const char* new_name =
nullptr,
bool inject =
false, q_setpub_t set_pub = CSP_UNCHANGED);
1809 DLLLOCAL
void importHashDecl(
ExceptionSink* xsink, qore_program_private& from_pgm,
const char* path,
const char* new_name =
nullptr, q_setpub_t set_pub = CSP_UNCHANGED);
1811 DLLLOCAL
const char* addString(
const char* str) {
1812 str_set_t::iterator i = str_set.lower_bound(str);
1813 if (i == str_set.end() || strcmp(*i, str)) {
1814 str_vec.push_back(strdup(str));
1815 i = str_set.insert(i, str_vec.back());
1820 DLLLOCAL
void addFile(
const char*& file) {
1821 file = addString(file);
1822 printd(5,
"qore_program_private::addFile('%s')\n", file);
1823 addStatementToIndexIntern(&statementByFileIndex, file,
nullptr, -1,
nullptr, -1);
1826 DLLLOCAL
void addFile(
const char*& file,
const char*& source,
int offset) {
1827 file = addString(file);
1829 source = addString(source);
1831 printd(5,
"qore_program_private::addFile('%s', '%s', %d)\n", file, source ? source :
"(null)", offset);
1832 addStatementToIndexIntern(&statementByFileIndex, file,
nullptr, -1, source, offset);
1834 addStatementToIndexIntern(&statementByLabelIndex, source,
nullptr, -1, file, offset);
1838 DLLLOCAL
int addFeature(
const char* f) {
1840 strset_t::iterator i = featureList.lower_bound(f);
1841 if (i != featureList.end() && (*i == f)) {
1845 featureList.insert(i, f);
1849 DLLLOCAL
void removeFeature(
const char* f) {
1850 strset_t::iterator i = featureList.find(f);
1851 assert(i != featureList.end());
1852 featureList.erase(i);
1855 DLLLOCAL
int addUserFeature(
const char* f) {
1857 strset_t::iterator i = userFeatureList.lower_bound(f);
1858 if (i != userFeatureList.end() && (*i == f)) {
1862 userFeatureList.insert(i, f);
1866 DLLLOCAL
bool hasUserFeature(
const std::string feature)
const {
1867 return userFeatureList.find(feature) != userFeatureList.end();
1870 DLLLOCAL
void removeUserFeature(
const char* f) {
1871 strset_t::iterator i = userFeatureList.find(f);
1872 assert(i != userFeatureList.end());
1873 userFeatureList.erase(i);
1876 DLLLOCAL
bool hasFeature(
const char* f)
const {
1877 return (featureList.find(f) != featureList.end())
1878 || (userFeatureList.find(f) != userFeatureList.end());
1881 DLLLOCAL
void runtimeImportSystemClassesIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1882 DLLLOCAL
void runtimeImportSystemConstantsIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1883 DLLLOCAL
void runtimeImportSystemFunctionsIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1884 DLLLOCAL
void runtimeImportSystemHashDeclsIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1886 DLLLOCAL
void runtimeImportSystemClasses(
ExceptionSink* xsink);
1887 DLLLOCAL
void runtimeImportSystemConstants(
ExceptionSink* xsink);
1888 DLLLOCAL
void runtimeImportSystemFunctions(
ExceptionSink* xsink);
1889 DLLLOCAL
void runtimeImportSystemHashDecls(
ExceptionSink* xsink);
1898 assert(extmap.find(owner) == extmap.end());
1899 extmap.insert(extmap_t::value_type(owner, pud));
1904 extmap_t::const_iterator i = extmap.find(owner);
1905 return i == extmap.end() ? nullptr : i->second;
1910 extmap_t::iterator i = extmap.find(owner);
1911 if (i == extmap.end()) {
1920 return qore_root_ns_private::getGlobalVars(*RootNS);
1923 DLLLOCAL LocalVar* createLocalVar(
const char* name,
const QoreTypeInfo* typeInfo);
1925 DLLLOCAL
const AbstractQoreFunctionVariant* runtimeFindCall(
const char* name,
const QoreListNode* params,
ExceptionSink* xsink);
1930 return pgm.priv->runtimeFindClass(class_name, xsink);
1934 pgm.priv->doThreadInit(xsink);
1939 if (!pgm.priv->exec_class) {
1940 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>))");
1943 pgm.priv->exec_class_rv.discard(xsink);
1944 pgm.priv->exec_class_rv = rv.release();
1950 return pgm.priv->preregisterNewThread(xsink);
1954 DLLLOCAL
static void cancelPreregistration(
QoreProgram& pgm) {
1955 pgm.priv->cancelPreregistration();
1959 DLLLOCAL
static void registerNewThread(
QoreProgram& pgm,
int tid) {
1960 pgm.priv->registerNewThread(tid);
1964 pgm.priv->runtimeImportSystemClasses(xsink);
1968 pgm.priv->runtimeImportSystemHashDecls(xsink);
1972 pgm.priv->runtimeImportSystemConstants(xsink);
1976 pgm.priv->runtimeImportSystemFunctions(xsink);
1980 pgm.priv->runtimeImportSystemApi(xsink);
1983 DLLLOCAL
static qore_program_private* get(
QoreProgram& pgm) {
1988 pgm.priv->clearThreadData(xsink);
1991 DLLLOCAL
static void addStatement(
QoreProgram& pgm, AbstractStatement* s) {
1992 pgm.priv->addStatement(s);
1995 DLLLOCAL
static const AbstractQoreZoneInfo* currentTZIntern(
QoreProgram& pgm) {
1996 return pgm.priv->TZ;
2000 return pgm.priv->lockParsing(xsink);
2003 DLLLOCAL
static void unlockParsing(
QoreProgram& pgm) {
2004 pgm.priv->unlockParsing();
2008 return pgm.priv->incThreadCount(xsink);
2011 DLLLOCAL
static void decThreadCount(
QoreProgram& pgm,
int tid) {
2012 pgm.priv->decThreadCount(tid);
2016 DLLLOCAL
static void addSignal(
QoreProgram& pgm,
int sig) {
2017 assert(pgm.priv->sigset.find(sig) == pgm.priv->sigset.end());
2018 pgm.priv->sigset.insert(sig);
2022 DLLLOCAL
static void delSignal(
QoreProgram& pgm,
int sig) {
2023 assert(pgm.priv->sigset.find(sig) != pgm.priv->sigset.end());
2024 pgm.priv->sigset.erase(sig);
2028 pgm.priv->qore_program_private_base::startThread(xsink);
2033 return pgm.priv->setThreadInit(n_thr_init, xsink);
2038 return pgm->priv->runtimeGetCallReference(name, xsink);
2041 DLLLOCAL
static const ParseWarnOptions& getParseWarnOptions(
const QoreProgram* pgm) {
2042 return pgm->priv->pwo;
2045 DLLLOCAL
static bool setSaveParseWarnOptions(
const QoreProgram* pgm,
const ParseWarnOptions &new_opts,
2046 ParseWarnOptions &old_opts) {
2047 if (new_opts == pgm->priv->pwo)
2049 old_opts = pgm->priv->pwo;
2050 pgm->priv->pwo = new_opts;
2054 DLLLOCAL
static void setParseWarnOptions(
const QoreProgram* pgm,
const ParseWarnOptions &new_opts) {
2055 pgm->priv->pwo = new_opts;
2058 DLLLOCAL
static bool setThreadVarData(
QoreProgram* pgm, ThreadProgramData* td, ThreadLocalProgramData* &tlpd,
2060 return pgm->priv->setThreadVarData(td, tlpd, run);
2064 pgm->priv->makeParseException(loc,
"PARSE-EXCEPTION", desc);
2067 DLLLOCAL
static void makeParseException(
QoreProgram* pgm,
const QoreProgramLocation &loc,
const char* err,
2069 pgm->priv->makeParseException(loc, err, desc);
2074 return pgm->priv->getDefine(name, is_defined);
2077 DLLLOCAL
static const QoreValue parseGetDefine(
QoreProgram* pgm,
const char* name,
bool& is_defined) {
2078 return pgm->priv->getDefine(name, is_defined);
2083 return pgm->priv->runTimeGetDefine(name, is_defined);
2086 DLLLOCAL
static QoreValue runTimeGetDefine(
QoreProgram* pgm,
const char* name,
bool& is_defined) {
2087 return pgm->priv->runTimeGetDefine(name, is_defined);
2091 return pgm->priv->runTimeGetAllDefines();
2094 DLLLOCAL
static bool parseUnDefine(
QoreProgram* pgm,
const char* name) {
2095 return pgm->priv->parseUnDefine(name);
2099 return pgm->priv->runTimeUnDefine(name, xsink);
2102 DLLLOCAL
static bool parseIsDefined(
QoreProgram* pgm,
const char* name) {
2103 return pgm->priv->isDefined(name);
2106 DLLLOCAL
static bool runTimeIsDefined(
QoreProgram* pgm,
const char* name) {
2107 return pgm->priv->runTimeIsDefined(name);
2110 DLLLOCAL
static void parseDefine(
QoreProgram* pgm,
const QoreProgramLocation* loc,
const char* str,
QoreValue val) {
2111 pgm->priv->parseDefine(loc, str, val);
2115 pgm->priv->runTimeDefine(str, val, xsink);
2118 DLLLOCAL
static void addParseException(
QoreProgram* pgm,
ExceptionSink* xsink,
const QoreProgramLocation* loc =
nullptr) {
2120 pgm->priv->addParseException(*xsink, loc);
2124 DLLLOCAL
static void addParseException(
QoreProgram* pgm,
ExceptionSink& xsink,
const QoreProgramLocation* loc =
nullptr) {
2125 pgm->priv->addParseException(xsink, loc);
2128 DLLLOCAL
static void exportFunction(
QoreProgram* srcpgm,
ExceptionSink* xsink,
QoreProgram* trgpgm,
const char* name,
const char* new_name =
nullptr,
bool inject =
false) {
2129 srcpgm->priv->exportFunction(xsink, trgpgm->priv, name, new_name, inject);
2133 return pgm->priv->parseAddDomain(n_dom);
2137 return pgm.priv->dom;
2141 pgm.priv->dom |= n_dom;
2145 int64 rv = pgm.priv->pwo.parse_options;
2146 pgm.priv->pwo.parse_options = po;
2150 DLLLOCAL
static void makeParseWarning(
QoreProgram* pgm,
const QoreProgramLocation &loc,
int code,
const char* warn,
const char* fmt, ...) {
2152 if (!pgm->priv->warnSink || !(code & pgm->priv->pwo.warn_mask))
2158 va_start(args, fmt);
2159 int rc = desc->
vsprintf(fmt, args);
2164 QoreException *ne =
new ParseException(loc, warn, desc);
2165 pgm->priv->warnSink->raiseException(ne);
2168 DLLLOCAL
static void makeParseWarning(
QoreProgram* pgm,
const QoreProgramLocation &loc,
int code,
const char* warn,
QoreStringNode* desc) {
2170 if (!pgm->priv->warnSink || !(code & pgm->priv->pwo.warn_mask)) {
2175 QoreException *ne =
new ParseException(loc, warn, desc);
2176 pgm->priv->warnSink->raiseException(ne);
2180 pgm->priv->exportGlobalVariable(name, readonly, *(tpgm->priv), xsink);
2183 DLLLOCAL
void attachDebug(
const qore_debug_program_private* n_dpgm) {
2184 printd(5,
"qore_program_private::attachDebug(n_dpgm: %p), dpgm: %p\n", n_dpgm, dpgm);
2190 dpgm =
const_cast<qore_debug_program_private*
>(n_dpgm);
2191 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());
2192 for (
auto& i : pgm_data_map) {
2193 i.second->dbgPendingAttach();
2194 i.second->dbgBreak();
2198 DLLLOCAL
void detachDebug(
const qore_debug_program_private* n_dpgm) {
2199 printd(5,
"qore_program_private::detachDebug(n_dpgm: %p), dpgm: %p\n", n_dpgm, dpgm);
2202 assert(n_dpgm==dpgm);
2206 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());
2207 for (
auto& i : pgm_data_map) {
2208 i.second->dbgPendingDetach();
2213 DLLLOCAL
void onAttach(DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2214 DLLLOCAL
void onDetach(DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2215 DLLLOCAL
void onStep(
const StatementBlock *blockStatement,
const AbstractStatement *statement,
unsigned bkptId,
int &flow, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2216 DLLLOCAL
void onFunctionEnter(
const StatementBlock *statement, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2217 DLLLOCAL
void onFunctionExit(
const StatementBlock *statement,
QoreValue& returnValue, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2218 DLLLOCAL
void onException(
const AbstractStatement *statement, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2219 DLLLOCAL
void onExit(
const StatementBlock *statement,
QoreValue& returnValue, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink);
2221 DLLLOCAL
int breakProgramThread(
int tid) {
2222 printd(5,
"qore_program_private::breakProgramThread(), this: %p, tid: %d\n",
this,
q_gettid());
2224 for (
auto& i : pgm_data_map) {
2225 if (i.first->gettid() == tid) {
2226 i.second->dbgBreak();
2233 DLLLOCAL
void breakProgram() {
2234 printd(5,
"qore_program_private::breakProgram(), this: %p\n",
this);
2236 for (
auto& i : pgm_data_map) {
2237 i.second->dbgBreak();
2242 if (!bkpt ||
this == bkpt->pgm)
return;
2243 if (!checkAllowDebugging(xsink))
2249 breakpointList.push_back(bkpt);
2254 DLLLOCAL
void deleteAllBreakpoints() {
2256 for (QoreBreakpointList_t::iterator it = breakpointList.begin(); it != breakpointList.end(); ++it) {
2257 (*it)->unassignAllStatements();
2258 (*it)->pgm =
nullptr;
2261 breakpointList.clear();
2264 DLLLOCAL
void getBreakpoints(QoreBreakpointList_t &bkptList) {
2267 for (QoreBreakpointList_t::iterator it = breakpointList.begin(); it != breakpointList.end(); ++it) {
2268 bkptList.push_back(*it);
2273 DLLLOCAL
void getStatementBreakpoints(
const AbstractStatement* statement, QoreBreakpointList_t &bkptList) {
2276 if (statement->breakpoints) {
2277 for (std::list<QoreBreakpoint*>::iterator it = statement->breakpoints->begin(); it != statement->breakpoints->end(); ++it) {
2278 bkptList.push_back(*it);
2284 DLLLOCAL
inline unsigned onCheckBreakpoint(
const AbstractStatement *statement,
ExceptionSink* xsink) {
2294 DLLLOCAL
unsigned long getStatementId(
const AbstractStatement* statement)
const {
2298 ReverseStatementIdMap_t::const_iterator i = reverseStatementIds.find((AbstractStatement*) statement);
2299 if (i == reverseStatementIds.end())
2306 if (statementId == 0 || statementId > statementIds.size())
2308 return statementIds[statementId-1];
2311 DLLLOCAL
unsigned getProgramId()
const {
2324 qore_root_ns_private::clearData(*RootNS, xsink);
2327 DLLLOCAL
static QoreProgram* resolveProgramId(
unsigned programId) {
2328 printd(5,
"qore_program_private::resolveProgramId(%x)\n", programId);
2330 for (qore_program_to_object_map_t::iterator i = qore_program_to_object_map.begin(); i != qore_program_to_object_map.end(); i++) {
2331 if (i->first->priv->programId == programId)
2340 xsink->
raiseException(
"DEBUGGING",
"program does not provide internal data for debugging");
2348 DLLLOCAL
void addStatementToIndexIntern(name_section_sline_statement_map_t* statementIndex,
const char* key, AbstractStatement *statement,
int offs,
const char* section,
int sectionOffs);
2349 DLLLOCAL
static void registerStatement(
QoreProgram *pgm, AbstractStatement *statement,
bool addToIndex);
2350 DLLLOCAL
QoreHashNode* getSourceIndicesIntern(name_section_sline_statement_map_t* statementIndex,
ExceptionSink* xsink)
const;
2352 return getSourceIndicesIntern(&statementByLabelIndex, xsink);
2355 return getSourceIndicesIntern(&statementByFileIndex, xsink);
2358 DLLLOCAL AbstractStatement* getStatementFromIndex(
const char* name,
int line) {
2359 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d), this: %p, file#: %d, label#: %d\n", name, line,
this, statementByFileIndex.size(), statementByLabelIndex.size());
2361 name_section_sline_statement_map_t::iterator it;
2362 if (statementByFileIndex.empty()) {
2365 bool addOffs =
true;
2366 if (!name || *name ==
'\0') {
2367 if (statementByFileIndex.size() != 1)
2369 it = statementByFileIndex.begin();
2371 size_t l = strlen(name);
2372 it = statementByFileIndex.find(name);
2373 if (it == statementByFileIndex.end()) {
2374 it = statementByLabelIndex.find(name);
2375 if (it == statementByLabelIndex.end()) {
2378 it = statementByFileIndex.begin();
2379 while (it != statementByFileIndex.end()) {
2380 size_t k = strlen(it->first);
2382 if (strcmp(name, it->first + k - l) == 0) {
2384 if (k == l || name[0] ==
'/' || it->first[k-l-1] ==
'/') {
2391 if (it == statementByFileIndex.end()) {
2392 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) no suffix match, this: %p\n", name, line,
this);
2395 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found by file suffix match, this: %p\n", name, line,
this);
2398 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found by label full match, this: %p\n", name, line,
this);
2401 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found by file full match, this: %p\n", name, line,
this);
2404 sline_statement_map_t *ssm = &it->second->statementMap;
2405 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found '%s', this: %p, ssm#: %d\n", name, line, it->first,
this, ssm->size());
2406 if (ssm->size() == 0)
2409 sline_statement_map_t::iterator li = ssm->upper_bound(line);
2410 if (li == ssm->begin()) {
2411 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) no statement found by line #1, this: %p\n", name, line,
this);
2417 AbstractStatement* st =
nullptr;
2420 if (ln != li->first) {
2424 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) {
2425 int n = li->second->loc->end_line - li->second->loc->start_line;
2438 if (li == ssm->begin())
2443 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);
2445 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) no statement found by line #2, this: %p\n", name, line,
this);
2451 printd(5,
"qore_program_private::registerQoreObject() pgm: %p, pgmid: %d\n", pgm, getProgramId());
2453 qore_program_to_object_map_t::iterator i = qore_program_private::qore_program_to_object_map.find(pgm);
2454 assert(i != qore_program_private::qore_program_to_object_map.end());
2455 if (i->second && i->second != o) {
2456 xsink->
raiseException(
"PROGRAM-ERROR",
"The Program has already assigned QoreObject");
2463 printd(5,
"qore_program_private::unregisterQoreObject() pgm: %p, pgmid: %d\n", pgm, getProgramId());
2465 qore_program_to_object_map_t::iterator i = qore_program_private::qore_program_to_object_map.find(pgm);
2466 assert(i != qore_program_private::qore_program_to_object_map.end());
2467 assert(i->second == o);
2468 i->second =
nullptr;
2473 qore_program_to_object_map_t::iterator i = qore_program_to_object_map.find(pgm);
2474 if (i == qore_program_to_object_map.end()) {
2483 qore_program_to_object_map_t::iterator i = qore_program_to_object_map.find(pgm);
2484 assert(i != qore_program_to_object_map.end());
2486 printd(5,
"qore_program_private::getQoreObject() pgm: %p, pgmid: %d, second: %p\n", i->first, i->first->getProgramId(), i->second);
2490 printd(5,
"qore_program_private::getQoreObject() pgm: %p, pgmid: %d, new second: %p\n", pgm, pgm->
getProgramId(), i->second);
2500 qore_program_to_object_map_t::iterator i = qore_program_to_object_map.begin();
2501 while (i != qore_program_to_object_map.end()) {
2503 printd(5,
"qore_program_private::getAllQoreObjects() pgm: %p, pgmid: %d, second: %p\n", i->first, i->first->getProgramId(), i->second);
2507 printd(5,
"qore_program_private::getAllQoreObjects() pgm: %p, pgmid: %d, new second: %p\n", i->first, i->first->getProgramId(), i->second);
2510 (*l)->push(i->second,
nullptr);
2517 class ParseWarnHelper :
public ParseWarnOptions {
2521 DLLLOCAL ParseWarnHelper(
const ParseWarnOptions &new_opts) {
2523 restore = pgm ? qore_program_private::setSaveParseWarnOptions(pgm, new_opts, *
this) : false;
2525 DLLLOCAL ~ParseWarnHelper() {
2527 qore_program_private::setParseWarnOptions(
getProgram(), *
this);
2531 typedef std::map<QoreProgram*, qore_program_private*> qore_program_map_t;
2534 class qore_debug_program_private {
2539 qore_program_map_t qore_program_map;
2542 DLLLOCAL qore_debug_program_private(
QoreDebugProgram *n_dpgm): dpgm(n_dpgm) {};
2543 DLLLOCAL ~qore_debug_program_private() {
2544 assert(qore_program_map.empty());
2548 if (!pgm->priv->checkAllowDebugging(xsink))
2551 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2552 printd(5,
"qore_debug_program_private::addProgram(), this: %p, pgm: %p, i: %p, end: %p\n",
this, pgm, i, qore_program_map.end());
2553 if (i != qore_program_map.end())
2555 qore_program_map.insert(qore_program_map_t::value_type(pgm, pgm->priv));
2557 pgm->priv->attachDebug(
this);
2562 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2563 printd(5,
"qore_debug_program_private::removeProgram(), this: %p, pgm: %p, i: %p, end: %p\n",
this, pgm, i, qore_program_map.end());
2564 if (i == qore_program_map.end())
2566 pgm->priv->detachDebug(
this);
2567 qore_program_map.erase(i);
2572 DLLLOCAL
void removeAllPrograms() {
2574 printd(5,
"qore_debug_program_private::removeAllPrograms(), this: %p\n",
this);
2575 qore_program_map_t::iterator i;
2576 while ((i = qore_program_map.begin()) != qore_program_map.end()) {
2577 qore_program_private* qpp = i->second;
2579 qore_program_map.erase(i);
2580 qpp->detachDebug(
this);
2587 printd(5,
"qore_debug_program_private::getAllProgramObjects(), this: %p\n",
this);
2589 qore_program_map_t::iterator i = qore_program_map.begin();
2590 while (i != qore_program_map.end()) {
2593 (*l)->push(o,
nullptr);
2600 DLLLOCAL
void onAttach(
QoreProgram *pgm, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2601 AutoQoreCounterDec ad(&debug_program_counter);
2602 dpgm->onAttach(pgm, rs, rts, xsink);
2604 DLLLOCAL
void onDetach(
QoreProgram *pgm, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2605 AutoQoreCounterDec ad(&debug_program_counter);
2606 dpgm->onDetach(pgm, rs, rts, xsink);
2614 DLLLOCAL
void onStep(
QoreProgram *pgm,
const StatementBlock *blockStatement,
const AbstractStatement *statement,
unsigned bkptId,
int &flow, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2615 AutoQoreCounterDec ad(&debug_program_counter);
2616 dpgm->
onStep(pgm, blockStatement, statement, bkptId, flow, rs, rts, xsink);
2619 DLLLOCAL
void onFunctionEnter(
QoreProgram *pgm,
const StatementBlock *statement, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2620 AutoQoreCounterDec ad(&debug_program_counter);
2626 DLLLOCAL
void onFunctionExit(
QoreProgram *pgm,
const StatementBlock *statement,
QoreValue& returnValue, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2627 AutoQoreCounterDec ad(&debug_program_counter);
2628 dpgm->
onFunctionExit(pgm, statement, returnValue, rs, rts, xsink);
2633 DLLLOCAL
void onException(
QoreProgram* pgm,
const AbstractStatement* statement, DebugRunStateEnum& rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2634 AutoQoreCounterDec ad(&debug_program_counter);
2635 dpgm->
onException(pgm, statement, rs, rts, xsink);
2640 DLLLOCAL
void onExit(
QoreProgram *pgm,
const StatementBlock *statement,
QoreValue& returnValue, DebugRunStateEnum &rs,
const AbstractStatement *&rts,
ExceptionSink* xsink) {
2641 AutoQoreCounterDec ad(&debug_program_counter);
2642 dpgm->
onExit(pgm, statement, returnValue, rs, rts, xsink);
2645 DLLLOCAL
int breakProgramThread(
QoreProgram* pgm,
int tid) {
2652 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2653 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);
2654 if (i == qore_program_map.end())
2656 if (i->second->breakProgramThread(tid))
2668 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2669 printd(5,
"qore_debug_program_private::breakProgram(), this: %p, pgm: %p, i: %p, end: %p\n",
this, pgm, i, qore_program_map.end());
2670 if (i == qore_program_map.end())
2672 i->second->breakProgram();
2676 DLLLOCAL
void waitForTerminationAndClear(
ExceptionSink* xsink) {
2677 removeAllPrograms();
2682 DLLLOCAL
int getInterruptedCount() {
2683 return debug_program_counter.
getCount();
DLLEXPORT const QoreEncoding * QCS_DEFAULT
the default encoding for the Qore library
DLLEXPORT char * q_basenameptr(const char *path)
returns a pointer within the same string
#define PO_NO_LOCALE_CONTROL
do not allow changes to program locale
Definition: Restrictions.h:64
#define PO_NO_CHILD_PO_RESTRICTIONS
turn off parse option inheritance restrictions
Definition: Restrictions.h:51
#define PO_ALLOW_INJECTION
allow code injection
Definition: Restrictions.h:76
#define PO_POSITIVE_OPTIONS
mask of all options allowing for more freedom (instead of less)
Definition: Restrictions.h:132
#define PO_FREE_OPTIONS
mask of options that have no effect on code access or code safety
Definition: Restrictions.h:135
#define PO_NO_DEBUGGING
disallows debugging actions that could be insecure such as reading the thread local variable stack
Definition: Restrictions.h:86
DLLLOCAL void ref() const
increments the reference count of the object
Definition: AbstractPrivateData.h:51
DLLEXPORT void deref(ExceptionSink *xsink)
decrements the reference count and calls derefImpl() if there_can_be_only_one is false,...
an abstract class for program-specific external data
Definition: QoreProgram.h:999
provides a safe and exception-safe way to hold locks in Qore, only to be used on the stack,...
Definition: QoreThreadLock.h:136
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:48
DLLEXPORT void assimilate(ExceptionSink *xs)
assimilates all entries of the "xs" argument by appending them to the internal list and deletes the "...
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 AbstractQoreNode * raiseException(const char *err, const char *fmt,...)
appends a Qore-language exception to the list
DLLEXPORT void clear()
deletes the exception list immediately
DLLEXPORT bool isException() const
returns true if at least one exception is present
provides a safe and exception-safe way to hold read locks in Qore, only to be used on the stack,...
Definition: QoreRWLock.h:105
provides a safe and exception-safe way to hold write locks in Qore, only to be used on the stack,...
Definition: QoreRWLock.h:144
Class implementing breakpoint for debugging.
Definition: QoreProgram.h:1038
DLLEXPORT AbstractStatement * resolveStatementId(unsigned long statementId, ExceptionSink *xsink) const
DLLEXPORT unsigned getBreakpointId() const
get the breakpoint id
DLLEXPORT void assignProgram(QoreProgram *new_pgm, ExceptionSink *xsink)
defines a Qore-language class
Definition: QoreClass.h:249
DLLEXPORT const QoreTypeInfo * getTypeInfo() const
returns the type information structure for this class
a thread condition class implementing a wrapper for pthread_cond_t
Definition: QoreCondition.h:45
DLLEXPORT int wait(pthread_mutex_t *m)
blocks a thread on a mutex until the condition is signaled
DLLEXPORT int broadcast()
singles all threads blocked on this condition to wake up
a simple thread-safe counter object; objects can block on it until the counter reaches zero
Definition: QoreCounter.h:40
DLLEXPORT int dec(ExceptionSink *xsink)
decrements the counter and wakes up any threads if the counter reaches 0
DLLEXPORT int getCount() const
returns the current count
DLLEXPORT int inc()
increments the counter
DLLEXPORT int waitForZero(ExceptionSink *xsink, int timeout_ms=0)
blocks the calling thread until the counter reaches 0
supports parsing and executing Qore-language code, reference counted, dynamically-allocated only
Definition: QoreDebugProgram.h:66
virtual DLLEXPORT void onFunctionEnter(QoreProgram *pgm, const StatementBlock *statement, DebugRunStateEnum &rs, const AbstractStatement *&rts, ExceptionSink *xsink)
virtual DLLEXPORT void onStep(QoreProgram *pgm, const StatementBlock *blockStatement, const AbstractStatement *statement, unsigned bkptId, int &flow, DebugRunStateEnum &rs, const AbstractStatement *&rts, ExceptionSink *xsink)
virtual DLLEXPORT void onFunctionExit(QoreProgram *pgm, const StatementBlock *statement, QoreValue &returnValue, DebugRunStateEnum &rs, const AbstractStatement *&rts, ExceptionSink *xsink)
virtual DLLEXPORT void onExit(QoreProgram *pgm, const StatementBlock *statement, QoreValue &returnValue, DebugRunStateEnum &rs, const AbstractStatement *&rts, ExceptionSink *xsink)
virtual DLLEXPORT void onException(QoreProgram *pgm, const AbstractStatement *statement, DebugRunStateEnum &rs, const AbstractStatement *&rts, ExceptionSink *xsink)
This is the hash or associative list container type in Qore, dynamically allocated only,...
Definition: QoreHashNode.h:50
DLLEXPORT size_t size() const
returns the number of members in the hash, executes in constant time
DLLEXPORT QoreHashNode * copy() const
performs a copy of the hash and returns the new hash
This is the list container type in Qore, dynamically allocated only, reference counted.
Definition: QoreListNode.h:52
DLLEXPORT int push(QoreValue val, ExceptionSink *xsink)
adds a value to the list
DLLEXPORT QoreListNode * copy() const
performs a deep copy of the list and returns the new list
contains constants, classes, and subnamespaces in QoreProgram objects
Definition: QoreNamespace.h:65
the implementation of Qore's object data type, reference counted, dynamically-allocated only
Definition: QoreObject.h:60
supports parsing and executing Qore-language code, reference counted, dynamically-allocated only
Definition: QoreProgram.h:127
static DLLEXPORT QoreObject * getQoreObject(QoreProgram *pgm)
get QoreObject of QoreProgram
DLLEXPORT unsigned getProgramId() const
get the program id
virtual DLLEXPORT void deref(ExceptionSink *xsink)
decrements the reference count of the object
provides a simple POSIX-threads-based read-write lock
Definition: QoreRWLock.h:47
provides atomic reference counting to Qore objects
Definition: QoreReferenceCounter.h:44
DLLEXPORT void ROreference() const
atomically increments the reference count
DLLEXPORT int reference_count() const
gets the reference count
DLLEXPORT bool ROdereference() const
atomically decrements the reference count
abstract base class for c++ Exceptions in the Qore library
Definition: QoreStandardException.h:49
Qore's string type supported by the QoreEncoding class.
Definition: QoreString.h:93
DLLEXPORT size_t strlen() const
returns number of bytes in the string (not including the null pointer)
DLLEXPORT bool empty() const
returns true if the string is empty, false if not
DLLEXPORT int vsprintf(const char *fmt, va_list args)
this will concatentate a formatted string to the existing string according to the format string and t...
DLLEXPORT const char * c_str() const
returns the string's buffer; this data should not be changed
DLLEXPORT const char * getBuffer() const
returns the string's buffer; this data should not be changed
Qore's string value type, reference counted, dynamically-allocated only.
Definition: QoreStringNode.h:50
provides access to thread-local storage
Definition: QoreThreadLocalStorage.h:44
DLLLOCAL void set(T *ptr)
sets the key's value
Definition: QoreThreadLocalStorage.h:82
DLLLOCAL T * get()
retrieves the key's value
Definition: QoreThreadLocalStorage.h:77
provides a mutually-exclusive thread lock
Definition: QoreThreadLock.h:49
base class for resolved call references
Definition: CallReferenceNode.h:109
the root namespace of a QoreProgram object
Definition: QoreNamespace.h:397
Helps dereference values outside of locks.
Definition: QoreLibIntern.h:543
DLLLOCAL void add(QoreValue v)
adds a value for dereferencing on exit
Definition: QoreLibIntern.h:568
provides an exception-safe way to manage locks in Qore, only to be used on the stack,...
Definition: QoreThreadLock.h:228
use this class to manage strings where the character encoding must be specified and may be different ...
Definition: QoreString.h:1104
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:1145
typed hash declaration
Definition: TypedHashDecl.h:44
holds an object and dereferences it in the destructor
Definition: QoreValue.h:476
non-thread-safe vector for storing "char*" that you want to delete
Definition: common.h:238
std::set< int > int_set_t
set of integers
Definition: common.h:82
long long int64
64bit integer type, cannot use int64_t here since it breaks the API on some 64-bit systems due to equ...
Definition: common.h:260
DLLEXPORT QoreProgram * getProgram()
returns the current QoreProgram
DLLEXPORT const AbstractQoreZoneInfo * currentTZ()
returns the current local time zone, note that if 0 = UTC
DLLEXPORT int q_gettid() noexcept
returns the current TID number
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:275