32#ifndef _QORE_QORE_PROGRAM_PRIVATE_H
33#define _QORE_QORE_PROGRAM_PRIVATE_H
40#include "qore/intern/ParserSupport.h"
41#include "qore/intern/QoreNamespaceIntern.h"
42#include "qore/intern/QC_AutoReadLock.h"
43#include "qore/intern/QC_AutoWriteLock.h"
44#include "qore/intern/QC_Program.h"
45#include "qore/intern/QC_ProgramControl.h"
46#include "qore/intern/ReturnStatement.h"
47#include "qore/intern/StreamReader.h"
48#include "qore/intern/StreamWriter.h"
50#include "qore/QoreDebugProgram.h"
51#include "qore/QoreRWLock.h"
52#include "qore/vector_map"
53#include "qore/vector_set"
61typedef vector_map_t<int, unsigned> ptid_map_t;
64typedef std::vector<AbstractStatement*> stmt_vec_t;
66class QoreParseLocationHelper {
68 DLLLOCAL QoreParseLocationHelper(
const char* file,
const char* src =
nullptr,
int offset = 0) {
70 thread_set_class_and_ns(
nullptr,
nullptr, cls, ns);
71 beginParsing(file,
nullptr, src, offset);
74 DLLLOCAL ~QoreParseLocationHelper() {
76 thread_set_class_and_ns(cls, ns);
81 const qore_class_private* cls;
86typedef safe_dslist<LocalVar*> local_var_list_t;
89typedef StatementBlock* q_exp_t;
91class LocalVariableList :
public local_var_list_t {
93 DLLLOCAL LocalVariableList() {
96 DLLLOCAL ~LocalVariableList() {
97 for (local_var_list_t::iterator i = begin(), e = end(); i != e; ++i) {
105#include "qore/intern/ThreadLocalVariableData.h"
106#include "qore/intern/ThreadClosureVariableStack.h"
108hashdecl ThreadLocalProgramData {
111 ThreadLocalVariableData lvstack;
113 ThreadClosureVariableStack cvstack;
115 const AbstractQoreZoneInfo* tz =
nullptr;
122 DLLLOCAL ThreadLocalProgramData() : tz_set(false), inst(false) {
123 printd(5,
"ThreadLocalProgramData::ThreadLocalProgramData() this: %p\n",
this);
126 DLLLOCAL ~ThreadLocalProgramData() {
127 printd(5,
"ThreadLocalProgramData::~ThreadLocalProgramData() this: %p, rs: %d\n",
this, runState);
128 assert(lvstack.empty());
129 assert(cvstack.empty());
133 lvstack.finalize(sdh);
134 cvstack.finalize(sdh);
143 DLLLOCAL
void setTZ(
const AbstractQoreZoneInfo* n_tz) {
148 DLLLOCAL
void clearTZ() {
186 DLLLOCAL
int dbgStep(
const StatementBlock* blockStatement,
const AbstractStatement* statement,
ExceptionSink* xsink);
190 DLLLOCAL
void dbgFunctionEnter(
const StatementBlock* statement,
ExceptionSink* xsink);
194 DLLLOCAL
void dbgFunctionExit(
const StatementBlock* statement,
QoreValue& returnValue,
ExceptionSink* xsink);
198 DLLLOCAL
void dbgException(
const AbstractStatement* statement,
ExceptionSink* xsink);
207 DLLLOCAL
void dbgBreak() {
208 printd(5,
"ThreadLocalProgramData::dbgBreak(), this: %p\n",
this);
214 DLLLOCAL
void dbgPendingAttach() {
215 printd(5,
"ThreadLocalProgramData::dbgPendingAttach(), this: %p\n",
this);
221 DLLLOCAL
void dbgPendingDetach() {
222 printd(5,
"ThreadLocalProgramData::dbgPendingDetach(), this: %p\n",
this);
229 DLLLOCAL
bool dbgIsAttached() {
230 return runState != DBG_RS_DETACH;
233 DLLLOCAL
bool runtimeCheck()
const {
234 return runState != DBG_RS_DETACH || attachFlag || breakFlag;
239 DLLLOCAL ThreadLocalProgramData(
const ThreadLocalProgramData& old) =
delete;
242 DebugRunStateEnum runState = DBG_RS_DETACH;
244 const AbstractStatement* runToStatement =
nullptr;
246 int functionCallLevel = 0;
248 DLLLOCAL
inline void setRunState(DebugRunStateEnum rs,
const AbstractStatement* rts) {
249 assert(rs < DBG_RS_STOPPED);
250 if (rs == DBG_RS_UNTIL_RETURN) {
251 functionCallLevel = 1;
253 printd(5,
"ThreadLocalProgramData::setRunState(), this: %p, rs: %d->%d, rts: %p\n",
this, runState, rs, rts);
255 runToStatement = rts;
258 volatile bool breakFlag =
false;
260 DLLLOCAL
inline void checkBreakFlag() {
261 if (breakFlag && runState != DBG_RS_DETACH) {
263 if (runState != DBG_RS_STOPPED) {
264 runState = DBG_RS_STEP;
266 printd(5,
"ThreadLocalProgramData::checkBreakFlag(), this: %p, rs: %d\n",
this, runState);
272 if (attachFlag && runState != DBG_RS_STOPPED) {
273 if (attachFlag > 0) {
278 }
else if (attachFlag < 0) {
287typedef vector_map_t<ThreadProgramData*, ThreadLocalProgramData*> pgm_data_map_t;
291typedef vector_map_t<std::string, QoreValue> dmap_t;
295typedef vector_map_t<const char*, int64> ppo_t;
298class AbstractQoreZoneInfo;
302 DLLLOCAL
bool operator()(
const QoreProgramLocation* p1,
const QoreProgramLocation* p2)
const {
310hashdecl pgmloc_vec_t :
public std::vector<QoreProgramLocation*> {
311 DLLLOCAL ~pgmloc_vec_t() {
315 DLLLOCAL
void clear() {
316 for (
auto& i : *this) {
320 std::vector<QoreProgramLocation*>::clear();
324class qore_program_private_base {
325 friend class QoreProgramAccessHelper;
328 LocalVariableList local_var_list;
333 unsigned thread_count = 0;
334 unsigned thread_waiting = 0;
335 unsigned parse_count = 0;
345 typedef std::set<const char*, ltstr> str_set_t;
349 typedef std::set<const QoreProgramLocation*, ltpgm> loc_set_t;
352 typedef std::set<std::string> strset_t;
354 strset_t featureList;
357 strset_t userFeatureList;
360 strset_t parse_modules;
371 * warnSink =
nullptr,
372 * pendingParseSink =
nullptr;
377 TopLevelStatementBlock sb;
380 bool only_first_except : 1,
382 po_allow_restrict : 1,
385 requires_exception : 1,
387 parsing_in_progress : 1,
393 typedef std::set<q_exp_t> q_exp_set_t;
395 q_exp_t new_expression =
nullptr;
399 int exceptions_raised = 0,
402 ParseWarnOptions pwo;
407 std::string exec_class_name, script_dir, script_path, script_name, include_path;
414 mutable unsigned twaiting = 0;
417 pgm_data_map_t pgm_data_map;
420 const AbstractQoreZoneInfo* TZ;
438 : plock(&ma_recursive),
440 only_first_except(false),
442 po_allow_restrict(true),
445 requires_exception(false),
447 parsing_in_progress(false),
450 expression_mode(false),
451 pwo(n_parse_options),
453 printd(QPP_DBG_LVL,
"qore_program_private_base::qore_program_private_base() this: %p pgm: %p po: " QLLD
"\n",
454 this, pgm, n_parse_options);
457 pgm->priv = (qore_program_private*)
this;
460 setParent(p_pgm, n_parse_options);
462 TZ = QTZM.getLocalZoneInfo();
467 Var *var = qore_root_ns_private::runtimeCreateVar(*RootNS, *QoreNS,
"ARGV", listTypeInfo,
true);
469 var->setInitial(ARGV->
copy());
471 var = qore_root_ns_private::runtimeCreateVar(*RootNS, *QoreNS,
"QORE_ARGV", listTypeInfo,
true);
472 if (var && QORE_ARGV)
473 var->setInitial(QORE_ARGV->
copy());
475 var = qore_root_ns_private::runtimeCreateVar(*RootNS, *QoreNS,
"ENV", hashTypeInfo,
true);
477 var->setInitial(ENV->
copy());
482 DLLLOCAL ~qore_program_private_base() {
483 printd(QPP_DBG_LVL,
"qore_program_private_base::~qore_program_private_base() this: %p pgm: %p\n",
this, pgm);
487 DLLLOCAL
const QoreProgramLocation* getLocation(
int sline,
int eline);
488 DLLLOCAL
const QoreProgramLocation* getLocation(
const QoreProgramLocation&,
int sline,
int eline);
493 DLLLOCAL
int64 checkDeserializeParseOptions(
int64 po) {
497 return pwo.parse_options & ~po & ~PO_FREE_STYLE_OPTIONS;
500 DLLLOCAL
void replaceParseOptionsIntern(
int64 po) {
501 pwo.parse_options = po;
504 DLLLOCAL
bool checkSetParseOptions(
int64 po) {
510 DLLLOCAL
void setParseOptionsIntern(
int64 po) {
511 pwo.parse_options |= po;
514 DLLLOCAL
void addParseModule(
const char* mod) {
515 parse_modules.insert(mod);
519 typedef vector_map_t<const char*, AbstractQoreProgramExternalData*> extmap_t;
526 DLLLOCAL
void newProgram();
528 DLLLOCAL
void setDefines();
531class PreParseHelper {
533 qore_program_private_base *p;
537 DLLLOCAL PreParseHelper(qore_program_private_base *n_p) : p(n_p), swapped(false) {
539 if (!p->pendingParseSink)
541 p->parseSink = p->pendingParseSink;
546 DLLLOCAL ~PreParseHelper() {
548 p->parseSink =
nullptr;
553class qore_debug_program_private;
555class AutoQoreCounterDec {
557 DLLLOCAL AutoQoreCounterDec(
QoreCounter* n_cnt,
bool incNow =
true): cnt(n_cnt), incFlag(false) {
563 DLLLOCAL ~AutoQoreCounterDec() {
569 DLLLOCAL
void inc() {
578 DLLLOCAL AutoQoreCounterDec() {}
583class qore_program_private :
public qore_program_private_base {
585 typedef std::map<const char*, int, ltstr> section_offset_map_t;
587 typedef std::map<int, AbstractStatement*> sline_statement_map_t;
589 hashdecl section_sline_statement_map {
590 section_offset_map_t sectionMap;
591 sline_statement_map_t statementMap;
594 typedef section_sline_statement_map section_sline_statement_map_t;
596 typedef vector_map_t<const char*, section_sline_statement_map_t*> name_section_sline_statement_map_t;
601 DLLLOCAL ~qore_program_private();
603 DLLLOCAL
void registerProgram();
605 DLLLOCAL
void depRef() {
606 printd(QPP_DBG_LVL,
"qore_program_private::depRef() this: %p pgm: %p %d->%d\n",
this, pgm,
611 DLLLOCAL
void depDeref() {
612 printd(QPP_DBG_LVL,
"qore_program_private::depDeref() this: %p pgm: %p %d->%d\n",
this, pgm,
630 for (
auto& i : pgm_data_map) {
631 i.second->finalize(sdh);
637 for (
auto& i : pgm_data_map) {
638 i.second->del(xsink);
639 i.first->delProgram(pgm);
643 DLLLOCAL
void waitForTerminationAndClear(
ExceptionSink* xsink);
655 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed has already been deleted and therefore no "
656 "new threads can be started in it");
665 DLLLOCAL
void cancelPreregistration() {
669 assert(thread_count > 0);
670 if (!--thread_count && thread_waiting)
675 DLLLOCAL
void registerNewThread(
int tid) {
679 assert(thread_count);
701 if (ptid && ptid != tid) {
702 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed has already been deleted and therefore "
703 "cannot be accessed at runtime");
706 if (parsing_in_progress) {
707 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed is currently undergoing parsing and cannot "
708 "be accessed at runtime");
717 DLLLOCAL
void incThreadCount() {
723 if (ptid && ptid != tid) {
725 "therefore cannot be accessed at runtime");
727 if (parsing_in_progress) {
728 throw QoreStandardException(
"PROGRAM-ERROR",
"the Program accessed is currently undergoing parsing and "
729 "cannot be accessed at runtime");
736 DLLLOCAL
void decThreadCount(
int tid) {
740 ptid_map_t::iterator i = tidmap.find(tid);
741 assert(i != tidmap.end());
745 assert(thread_count > 0);
746 if (!--thread_count && thread_waiting)
755 for (
auto& i : tidmap) {
756 l.
push(i.first,
nullptr);
765 while (parse_tid != -1 && parse_tid != tid && !ptid) {
773 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed has already been deleted and "
774 "therefore cannot be accessed");
786 DLLLOCAL
void unlockParsing() {
790 assert(parse_count > 0);
791 if (!(--parse_count)) {
793 if (thread_waiting) {
799 DLLLOCAL
bool parsingLocked()
const {
804 DLLLOCAL
void waitForAllThreadsToTerminateIntern() {
807 ptid_map_t::iterator i = tidmap.find(tid);
808 unsigned adj = (i != tidmap.end() ? 1 : 0);
810 while ((thread_count - adj) || parse_count) {
817 DLLLOCAL
void waitForAllThreadsToTerminate() {
820 waitForAllThreadsToTerminateIntern();
823 DLLLOCAL
const char* parseGetScriptPath()
const {
824 return script_path.empty() ? nullptr : script_path.c_str();
827 DLLLOCAL
const char* parseGetScriptDir()
const {
828 return script_dir.empty() ? nullptr : script_dir.c_str();
831 DLLLOCAL
const char* parseGetScriptName()
const {
832 return script_name.empty() ? nullptr : script_name.c_str();
838 return script_path.empty() ? nullptr :
new QoreStringNode(script_path);
844 return script_dir.empty() ? nullptr :
new QoreStringNode(script_dir);
850 return script_name.empty() ? nullptr :
new QoreStringNode(script_name);
853 DLLLOCAL
void setScriptPathExtern(
const char* path) {
859 DLLLOCAL
void setScriptPath(
const char* path) {
869 script_dir =
"." QORE_DIR_SEP_STR;
870 script_path = script_dir + script_name;
874 script_dir.assign(path, p - path);
888 for (
auto& i : featureList) {
891 for (
auto& i : userFeatureList) {
900 DLLLOCAL
int internParsePending(
ExceptionSink* xsink,
const char* code,
const char* label,
901 const char* orig_src =
nullptr,
int offset = 0,
bool standard_parse =
true) {
905 assert(code && code[0]);
909 const char* sname = label;
910 const char* src = orig_src;
912 addFile(src, sname, offset);
920 QoreParseLocationHelper qplh(sname, src, offset);
923 beginParsing(sname,
nullptr, src, offset);
925 if (!parsing_in_progress) {
926 parsing_in_progress =
true;
935 yy_scan_string(code, lexer);
936 yyset_lineno(1, lexer);
940 printd(5,
"qore_program_private::internParsePending() returned from yyparse()\n");
944 if (standard_parse) {
945 printd(5,
"qore_program_private::internParsePending() parse exception: calling parseRollback()\n");
946 internParseRollback(xsink);
947 requires_exception =
false;
951 printd(5,
"qore_program_private::internParsePending() about to call yylex_destroy()\n");
952 yylex_destroy(lexer);
953 printd(5,
"qore_program_private::internParsePending() returned from yylex_destroy()\n");
962 if (pendingParseSink) {
964 pendingParseSink =
nullptr;
970 xsink->
raiseException(
"PARSE-ERROR",
"parsing can only happen once for each Program container");
977 const char* orig_src =
nullptr,
int offset = 0) {
980 ProgramRuntimeParseContextHelper pch(xsink, pgm);
986 if (checkParse(xsink)) {
990 startParsing(xsink, wS, wm);
992 int rc = internParsePending(xsink, code, label, orig_src, offset);
1001 DLLLOCAL
int internParseCommit(
bool standard_parse =
true);
1004 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1010 if (checkParse(xsink)) {
1014 startParsing(xsink, wS, wm);
1017 int rc = internParseCommit();
1020 parseSink =
nullptr;
1028 ProgramRuntimeParseContextHelper pch(xsink, pgm);
1034 internParseRollback(xsink);
1040 printd(5,
"QoreProgram::parse(fp: %p, name: %s, xsink: %p, wS: %p, wm: %d)\n", fp, name, xsink, wS, wm);
1046 printd(5,
"QoreProgram::parse(fp: %p, name: %s) EOF\n", fp, name);
1055 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1060 if (checkParse(xsink)) {
1064 startParsing(xsink, wS, wm);
1068 const char* sname = name;
1074 QoreParseLocationHelper qplh(sname);
1077 beginParsing(sname);
1079 if (!parsing_in_progress) {
1080 parsing_in_progress =
true;
1085 yyset_in(fp, lexer);
1090 internParseCommit();
1093 parseSink =
nullptr;
1099 yylex_destroy(lexer);
1100 if (only_first_except && exceptions_raised > 1)
1101 fprintf(stderr,
"\n%d exception(s) skipped\n\n", exceptions_raised);
1105 int wm,
const QoreString* source =
nullptr,
int offset = 0) {
1121 if (source && !source->empty() && !src.
set(source,
QCS_DEFAULT, xsink))
1124 parse(tstr->c_str(), tlstr->c_str(), xsink, wS, wm, source ? src->
c_str() : nullptr, offset);
1128 const char* orig_src =
nullptr,
int offset = 0) {
1131 assert(code && code[0]);
1134 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1139 if (checkParse(xsink)) {
1143 startParsing(xsink, wS, wm);
1146 if (!internParsePending(xsink, code, label, orig_src, offset))
1147 internParseCommit();
1150 parseSink =
nullptr;
1162 xsink->
raiseException(
"STATEMENT-ERROR",
"the statement cannot be empty");
1179 if (source && !source->empty() && !src.
set(source,
QCS_DEFAULT, xsink)) {
1183 return parseStatement(tstr->c_str(), tlstr->c_str(), xsink, wS, wm, source ? src->
c_str() : nullptr, offset);
1187 int wm,
const char* orig_src =
nullptr,
int offset = 0) {
1190 assert(code && code[0]);
1193 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1198 startParsing(xsink, wS, wm);
1201 if (!internParsePending(xsink, code, label, orig_src, offset,
false)) {
1202 internParseCommit(
false);
1204 parsing_in_progress =
false;
1208 parseSink =
nullptr;
1211 return *xsink ? -1 : 0;
1219 xsink->
raiseException(
"EXPRESSION-ERROR",
"the expression cannot be empty");
1234 if (source && !source->empty() && !src.
set(source,
QCS_DEFAULT, xsink))
1237 return parseExpression(tstr->c_str(), tlstr->c_str(), xsink, wS, wm, source ? src->
c_str() : nullptr, offset);
1241 int wm,
const char* orig_src =
nullptr,
int offset = 0) {
1244 assert(code && code[0]);
1247 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1252 assert(!expression_mode);
1253 assert(!new_expression);
1254 expression_mode =
true;
1256 QoreStringMaker exp_code(
"return (%s);", code);
1258 startParsing(xsink, wS, wm);
1261 if (!internParsePending(xsink, exp_code.c_str(), label, orig_src, offset,
false)) {
1262 internParseCommit(
false);
1264 parsing_in_progress =
false;
1268 parseSink =
nullptr;
1272 expression_mode =
false;
1273 q_exp_t rv = new_expression;
1274 if (new_expression) {
1276 exp_set.erase(new_expression);
1277 delete new_expression;
1280 new_expression =
nullptr;
1286 QORE_TRACE(
"QoreProgram::parseFile()");
1288 printd(5,
"QoreProgram::parseFile(%s)\n", filename);
1291 if (!(fp = fopen(filename,
"r"))) {
1292 if ((only_first_except && !exceptions_raised) || !only_first_except)
1293 xsink->
raiseErrnoException(
"PARSE-EXCEPTION", errno,
"cannot open qore script '%s'", filename);
1294 exceptions_raised++;
1297 ON_BLOCK_EXIT(fclose, fp);
1299 setScriptPath(filename);
1301 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1305 parse(fp, filename, xsink, wS, wm);
1309 assert(!str->
empty());
1323 if (source && !source->empty() && !src.
set(source,
QCS_DEFAULT, xsink))
1326 parsePending(tstr->c_str(), tlstr->c_str(), xsink, wS, wm, source ? src->
c_str() : nullptr, offset);
1330 DLLLOCAL
void importFunction(
ExceptionSink* xsink, QoreFunction *u,
const qore_ns_private& oldns,
const char* new_name =
nullptr,
bool inject =
false);
1338 thread_local_storage->
set(h);
1346 printd(5,
"QoreProgram::clearThreadData() this: %p h: %p (size: %d)\n",
this, h, h ? h->
size() : 0);
1356 thread_local_storage->
set(
nullptr);
1360 DLLLOCAL
void finalizeThreadData(ThreadProgramData* td,
SafeDerefHelper& sdh) {
1364 thread_local_storage->
set(
nullptr);
1372 pgm_data_map_t::iterator i = pgm_data_map.find(td);
1373 if (i != pgm_data_map.end()) {
1374 i->second->finalize(sdh);
1379 DLLLOCAL
int endThread(ThreadProgramData* td,
ExceptionSink* xsink) {
1380 ThreadLocalProgramData* tlpd =
nullptr;
1389 pgm_data_map_t::iterator i = pgm_data_map.find(td);
1390 if (i == pgm_data_map.end()) {
1394 pgm_data_map.erase(i);
1401 DLLLOCAL
void doTopLevelInstantiation(ThreadLocalProgramData& tlpd) {
1403 const LVList* lvl = sb.getLVList();
1405 for (
unsigned i = 0; i < lvl->size(); ++i) {
1406 lvl->lv[i]->instantiate(pwo.parse_options);
1416 DLLLOCAL
bool setThreadVarData(ThreadProgramData* td, ThreadLocalProgramData*& new_tlpd,
bool run) {
1430 pgm_data_map_t::iterator i = pgm_data_map.find(td);
1431 if (i == pgm_data_map.end()) {
1434 ThreadLocalProgramData* tlpd =
new ThreadLocalProgramData;
1436 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");
1440 pgm_data_map.insert(pgm_data_map_t::value_type(td, tlpd));
1445 printd(5,
"qore_program_private::setThreadVarData() (first) this: %p pgm: %p td: %p\n",
this, pgm, td);
1446 doTopLevelInstantiation(*tlpd);
1452 ThreadLocalProgramData* tlpd = pgm_data_map[td];
1457 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");
1459 if (run && !tlpd->inst) {
1460 doTopLevelInstantiation(*tlpd);
1466 DLLLOCAL
const AbstractQoreZoneInfo* currentTZ(ThreadProgramData* tpd = get_thread_program_data())
const {
1468 pgm_data_map_t::const_iterator i = pgm_data_map.find(tpd);
1469 if (i != pgm_data_map.end() && i->second->tz_set)
1470 return i->second->tz;
1474 DLLLOCAL
void setTZ(
const AbstractQoreZoneInfo* n_TZ) {
1478 DLLLOCAL
void exportFunction(
ExceptionSink* xsink, qore_program_private* p,
const char* name,
const char* new_name =
nullptr,
bool inject =
false) {
1480 xsink->
raiseException(
"FUNCTION-IMPORT-ERROR",
"cannot import a function from the same Program object");
1485 xsink->
raiseException(
"FUNCTION-IMPORT-ERROR",
"cannot import function \"%s\" in a Program object without PO_ALLOW_INJECTION set", name);
1489 const QoreFunction* u;
1490 const qore_ns_private* ns =
nullptr;
1493 ProgramRuntimeParseAccessHelper rah(xsink, pgm);
1496 u = qore_root_ns_private::runtimeFindFunction(*RootNS, name, ns);
1500 xsink->
raiseException(
"PROGRAM-IMPORTFUNCTION-NO-FUNCTION",
"function '%s' does not exist in the current program scope", name);
1503 p->importFunction(xsink,
const_cast<QoreFunction*
>(u), *ns, new_name, inject);
1507 DLLLOCAL
bool parseExceptionRaised()
const {
1512 DLLLOCAL
void disableParseOptionsIntern(
int64 po) {
1513 pwo.parse_options &= ~po;
1518 if (checkSetParseOptions(po)) {
1519 xsink->
raiseException(
"OPTIONS-LOCKED",
"parse options have been locked on this program object");
1523 setParseOptionsIntern(po);
1531 if (((po &
PO_FREE_OPTIONS) != po) && po_locked && !po_allow_restrict) {
1532 xsink->
raiseException(
"OPTIONS-LOCKED",
"parse options have been locked on this program object");
1536 disableParseOptionsIntern(po);
1543 xsink->
raiseException(
"OPTION-ERROR",
"the calling Program does not have the PO_NO_CHILD_PO_RESTRICTIONS option set, and therefore cannot call Program::replaceParseOptions()");
1548 replaceParseOptionsIntern(po);
1552 DLLLOCAL
int parseSetParseOptions(
const QoreProgramLocation* loc,
int64 po) {
1556 parse_error(*loc,
"parse options have been locked on this program object");
1560 setParseOptionsIntern(po);
1564 DLLLOCAL
int parseDisableParseOptions(
const QoreProgramLocation* loc,
int64 po) {
1567 if (((po &
PO_FREE_OPTIONS) != po) && po_locked && !po_allow_restrict) {
1568 parse_error(*loc,
"parse options have been locked on this program object");
1572 disableParseOptionsIntern(po);
1576 DLLLOCAL
void parseSetTimeZone(
const char* zone) {
1580 mergeParseException(xsink);
1584 const AbstractQoreZoneInfo *tz = (*zone ==
'-' || *zone ==
'+') ? QTZM.findCreateOffsetZone(zone, &xsink) : QTZM.findLoadRegion(zone, &xsink);
1587 mergeParseException(xsink);
1591 assert(tz || ((*zone ==
'-' || *zone ==
'+')));
1596 DLLLOCAL
void makeParseException(
const QoreProgramLocation& loc,
const char* err,
QoreStringNode* desc) {
1597 QORE_TRACE(
"QoreProgram::makeParseException()");
1600 if (!requires_exception) {
1601 if ((only_first_except && !exceptions_raised) || !only_first_except) {
1602 QoreException *ne =
new ParseException(loc, err, d.release());
1605 exceptions_raised++;
1609 DLLLOCAL
void parseException(
const QoreProgramLocation& loc,
const char* fmt, ...) {
1613 if (requires_exception)
1619 va_start(args, fmt);
1620 int rc = desc->
vsprintf(fmt, args);
1625 makeParseException(loc,
"PARSE-EXCEPTION", desc);
1631 dmap_t::iterator i = dmap.find(name);
1632 if (i != dmap.end()) {
1633 i->second.discard(xsink);
1643 DLLLOCAL
const QoreValue getDefine(
const char* name,
bool& is_defined) {
1644 dmap_t::iterator i = dmap.find(name);
1645 if (i != dmap.end()) {
1653 DLLLOCAL
QoreValue runTimeGetDefine(
const char* name,
bool& is_defined) {
1655 return getDefine(name, is_defined).refSelf();
1662 DLLLOCAL
bool unDefine(
const char* name,
ExceptionSink* xsink) {
1663 dmap_t::iterator i = dmap.find(name);
1664 if (i != dmap.end()) {
1665 i->second.discard(xsink);
1672 DLLLOCAL
bool parseUnDefine(
const char* name) {
1673 PreParseHelper pph(
this);
1674 return unDefine(name, parseSink);
1677 DLLLOCAL
bool runTimeUnDefine(
const char* name,
ExceptionSink* xsink) {
1679 return unDefine(name, xsink);
1683 DLLLOCAL
bool isDefined(
const char* name) {
1684 dmap_t::iterator i = dmap.find(name);
1685 return i == dmap.end() ? false :
true;
1688 DLLLOCAL
bool runTimeIsDefined(
const char* name) {
1690 return isDefined(name);
1693 DLLLOCAL
int checkDefine(
const QoreProgramLocation* loc,
const char* str,
ExceptionSink* xsink) {
1694 const char* p = str;
1696 xsink->
raiseException(*loc,
"PARSE-EXCEPTION", 0,
"illegal define variable '%s'; does not begin with an alphabetic character", p);
1701 if (!isalnum(*p) && *p !=
'_') {
1703 xsink->
raiseException(*loc,
"PARSE-EXCEPTION", 0,
"illegal character '%c' in define variable '%s'", *p, str);
1711 DLLLOCAL
void parseDefine(
const QoreProgramLocation* loc,
const char* str,
QoreValue val) {
1712 PreParseHelper pph(
this);
1714 if (checkDefine(loc, str, parseSink))
1717 setDefine(str, val, parseSink);
1721 const QoreProgramLocation* loc = get_runtime_location();
1723 if (checkDefine(loc, str, xsink))
1727 setDefine(str, val, xsink);
1732 ProgramRuntimeParseAccessHelper pah(xsink, pgm);
1735 return qore_root_ns_private::runtimeGetCallReference(*RootNS, name, xsink);
1738 DLLLOCAL
void pushParseOptions(
const char* pf) {
1740 ppo_t::iterator i = ppo.lower_bound(pf);
1741 if (i != ppo.end() && !strcmp(pf, i->first))
1743 ppo.insert(i, ppo_t::value_type(pf, pwo.parse_options));
1747 DLLLOCAL
void restoreParseOptions(
const char* pf) {
1748 ppo_t::iterator i = ppo.find(pf);
1749 if (i != ppo.end()) {
1751 pwo.parse_options = i->second;
1756 DLLLOCAL
void addParseException(
ExceptionSink& xsink,
const QoreProgramLocation* loc) {
1757 if (requires_exception) {
1764 xsink.overrideLocation(*loc);
1780 if ((pos & p_tmp) != pos) {
1781 rv = ((pos & p_tmp) ^ pos);
1785 int64 neg = (n_dom & ~PO_POSITIVE_OPTIONS);
1786 if (neg && (neg & pwo.parse_options)) {
1787 rv |= (neg & pwo.parse_options);
1795 DLLLOCAL
void exportGlobalVariable(
const char* name,
bool readonly, qore_program_private& tpgm,
ExceptionSink* xsink);
1802 DLLLOCAL
void setThreadTZ(ThreadProgramData* tpd,
const AbstractQoreZoneInfo* tz) {
1804 pgm_data_map_t::iterator i = pgm_data_map.find(tpd);
1805 assert(i != pgm_data_map.end());
1806 i->second->setTZ(tz);
1809 DLLLOCAL
const AbstractQoreZoneInfo* getThreadTZ(ThreadProgramData* tpd,
bool& set)
const {
1811 pgm_data_map_t::const_iterator i = pgm_data_map.find(tpd);
1812 assert(i != pgm_data_map.end());
1813 set = i->second->tz_set;
1814 return i->second->tz;
1817 DLLLOCAL
void clearThreadTZ(ThreadProgramData* tpd) {
1819 pgm_data_map_t::iterator i = pgm_data_map.find(tpd);
1820 assert(i != pgm_data_map.end());
1821 i->second->clearTZ();
1824 DLLLOCAL
void addStatement(AbstractStatement* s);
1828 return parseExpression(source, label, xsink);
1832 ProgramThreadCountContextHelper pch(xsink, pgm,
true);
1836 if (exp_set.find(exp) == exp_set.end()) {
1837 xsink->
raiseException(
"INVALID-EXPRESSION",
"expression not registered to this Program object");
1840 ThreadFrameBoundaryHelper tfbh(
true);
1846 return rv.release();
1849 DLLLOCAL
void deleteExpression(q_exp_t exp) {
1851 q_exp_set_t::iterator i = exp_set.find(exp);
1852 if (i != exp_set.end()) {
1858 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);
1860 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);
1862 DLLLOCAL
const char* addString(
const char* str) {
1863 str_set_t::iterator i = str_set.lower_bound(str);
1864 if (i == str_set.end() || strcmp(*i, str)) {
1865 str_vec.push_back(strdup(str));
1866 i = str_set.insert(i, str_vec.back());
1871 DLLLOCAL
void addFile(
const char*& file) {
1872 file = addString(file);
1873 printd(5,
"qore_program_private::addFile('%s')\n", file);
1874 addStatementToIndexIntern(&statementByFileIndex, file,
nullptr, -1,
nullptr, -1);
1877 DLLLOCAL
void addFile(
const char*& file,
const char*& source,
int offset) {
1878 file = addString(file);
1880 source = addString(source);
1882 printd(5,
"qore_program_private::addFile('%s', '%s', %d)\n", file, source ? source :
"(null)", offset);
1883 addStatementToIndexIntern(&statementByFileIndex, file,
nullptr, -1, source, offset);
1885 addStatementToIndexIntern(&statementByLabelIndex, source,
nullptr, -1, file, offset);
1889 DLLLOCAL
int addFeature(
const char* f) {
1891 strset_t::iterator i = featureList.lower_bound(f);
1892 if (i != featureList.end() && (*i == f)) {
1896 featureList.insert(i, f);
1900 DLLLOCAL
void removeFeature(
const char* f) {
1901 strset_t::iterator i = featureList.find(f);
1902 assert(i != featureList.end());
1903 featureList.erase(i);
1906 DLLLOCAL
int addUserFeature(
const char* f) {
1908 strset_t::iterator i = userFeatureList.lower_bound(f);
1909 if (i != userFeatureList.end() && (*i == f)) {
1913 userFeatureList.insert(i, f);
1917 DLLLOCAL
bool hasUserFeature(
const std::string feature)
const {
1918 return userFeatureList.find(feature) != userFeatureList.end();
1921 DLLLOCAL
void removeUserFeature(
const char* f) {
1922 strset_t::iterator i = userFeatureList.find(f);
1923 assert(i != userFeatureList.end());
1924 userFeatureList.erase(i);
1927 DLLLOCAL
bool hasFeature(
const char* f)
const {
1928 return (featureList.find(f) != featureList.end())
1929 || (userFeatureList.find(f) != userFeatureList.end());
1932 DLLLOCAL
void runtimeImportSystemClassesIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1933 DLLLOCAL
void runtimeImportSystemConstantsIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1934 DLLLOCAL
void runtimeImportSystemFunctionsIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1935 DLLLOCAL
void runtimeImportSystemHashDeclsIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1937 DLLLOCAL
void runtimeImportSystemClasses(
ExceptionSink* xsink);
1938 DLLLOCAL
void runtimeImportSystemConstants(
ExceptionSink* xsink);
1939 DLLLOCAL
void runtimeImportSystemFunctions(
ExceptionSink* xsink);
1940 DLLLOCAL
void runtimeImportSystemHashDecls(
ExceptionSink* xsink);
1949 assert(extmap.find(owner) == extmap.end());
1950 extmap.insert(extmap_t::value_type(owner, pud));
1955 extmap_t::const_iterator i = extmap.find(owner);
1956 return i == extmap.end() ? nullptr : i->second;
1961 extmap_t::iterator i = extmap.find(owner);
1962 if (i == extmap.end()) {
1971 return qore_root_ns_private::getGlobalVars(*RootNS);
1974 DLLLOCAL LocalVar* createLocalVar(
const char* name,
const QoreTypeInfo* typeInfo);
1976 DLLLOCAL
const AbstractQoreFunctionVariant* runtimeFindCall(
const char* name,
const QoreListNode* params,
ExceptionSink* xsink);
1981 return pgm.priv->runtimeFindClass(class_name, xsink);
1985 pgm.priv->doThreadInit(xsink);
1990 if (!pgm.priv->exec_class) {
1991 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>))");
1994 pgm.priv->exec_class_rv.discard(xsink);
1995 pgm.priv->exec_class_rv = rv.release();
2001 return pgm.priv->preregisterNewThread(xsink);
2005 DLLLOCAL
static void cancelPreregistration(
QoreProgram& pgm) {
2006 pgm.priv->cancelPreregistration();
2010 DLLLOCAL
static void registerNewThread(
QoreProgram& pgm,
int tid) {
2011 pgm.priv->registerNewThread(tid);
2015 pgm.priv->runtimeImportSystemClasses(xsink);
2019 pgm.priv->runtimeImportSystemHashDecls(xsink);
2023 pgm.priv->runtimeImportSystemConstants(xsink);
2027 pgm.priv->runtimeImportSystemFunctions(xsink);
2031 pgm.priv->runtimeImportSystemApi(xsink);
2034 DLLLOCAL
static qore_program_private* get(
QoreProgram& pgm) {
2039 pgm.priv->clearThreadData(xsink);
2042 DLLLOCAL
static void addStatement(
QoreProgram& pgm, AbstractStatement* s) {
2043 pgm.priv->addStatement(s);
2046 DLLLOCAL
static const AbstractQoreZoneInfo* currentTZIntern(
QoreProgram& pgm) {
2047 return pgm.priv->TZ;
2051 return pgm.priv->lockParsing(xsink);
2054 DLLLOCAL
static void unlockParsing(
QoreProgram& pgm) {
2055 pgm.priv->unlockParsing();
2059 return pgm.priv->incThreadCount(xsink);
2062 DLLLOCAL
static void decThreadCount(
QoreProgram& pgm,
int tid) {
2063 pgm.priv->decThreadCount(tid);
2067 DLLLOCAL
static void addSignal(
QoreProgram& pgm,
int sig) {
2068 assert(pgm.priv->sigset.find(sig) == pgm.priv->sigset.end());
2069 pgm.priv->sigset.insert(sig);
2073 DLLLOCAL
static void delSignal(
QoreProgram& pgm,
int sig) {
2074 assert(pgm.priv->sigset.find(sig) != pgm.priv->sigset.end());
2075 pgm.priv->sigset.erase(sig);
2079 pgm.priv->qore_program_private_base::startThread(xsink);
2084 return pgm.priv->setThreadInit(n_thr_init, xsink);
2089 return pgm->priv->runtimeGetCallReference(name, xsink);
2092 DLLLOCAL
static const ParseWarnOptions& getParseWarnOptions(
const QoreProgram* pgm) {
2093 return pgm->priv->pwo;
2096 DLLLOCAL
static bool setSaveParseWarnOptions(
const QoreProgram* pgm,
const ParseWarnOptions &new_opts,
2097 ParseWarnOptions &old_opts) {
2098 if (new_opts == pgm->priv->pwo)
2100 old_opts = pgm->priv->pwo;
2101 pgm->priv->pwo = new_opts;
2105 DLLLOCAL
static void setParseWarnOptions(
const QoreProgram* pgm,
const ParseWarnOptions &new_opts) {
2106 pgm->priv->pwo = new_opts;
2109 DLLLOCAL
static bool setThreadVarData(
QoreProgram* pgm, ThreadProgramData* td, ThreadLocalProgramData* &tlpd,
2111 return pgm->priv->setThreadVarData(td, tlpd, run);
2115 pgm->priv->makeParseException(loc,
"PARSE-EXCEPTION", desc);
2118 DLLLOCAL
static void makeParseException(
QoreProgram* pgm,
const QoreProgramLocation &loc,
const char* err,
2120 pgm->priv->makeParseException(loc, err, desc);
2125 return pgm->priv->getDefine(name, is_defined);
2128 DLLLOCAL
static const QoreValue parseGetDefine(
QoreProgram* pgm,
const char* name,
bool& is_defined) {
2129 return pgm->priv->getDefine(name, is_defined);
2134 return pgm->priv->runTimeGetDefine(name, is_defined);
2137 DLLLOCAL
static QoreValue runTimeGetDefine(
QoreProgram* pgm,
const char* name,
bool& is_defined) {
2138 return pgm->priv->runTimeGetDefine(name, is_defined);
2142 return pgm->priv->runTimeGetAllDefines();
2145 DLLLOCAL
static bool parseUnDefine(
QoreProgram* pgm,
const char* name) {
2146 return pgm->priv->parseUnDefine(name);
2150 return pgm->priv->runTimeUnDefine(name, xsink);
2153 DLLLOCAL
static bool parseIsDefined(
QoreProgram* pgm,
const char* name) {
2154 return pgm->priv->isDefined(name);
2157 DLLLOCAL
static bool runTimeIsDefined(
QoreProgram* pgm,
const char* name) {
2158 return pgm->priv->runTimeIsDefined(name);
2161 DLLLOCAL
static void parseDefine(
QoreProgram* pgm,
const QoreProgramLocation* loc,
const char* str,
2163 pgm->priv->parseDefine(loc, str, val);
2167 pgm->priv->runTimeDefine(str, val, xsink);
2171 const QoreProgramLocation* loc =
nullptr) {
2173 pgm->priv->addParseException(*xsink, loc);
2178 const QoreProgramLocation* loc =
nullptr) {
2179 pgm->priv->addParseException(xsink, loc);
2183 const char* name,
const char* new_name =
nullptr,
bool inject =
false) {
2184 srcpgm->priv->exportFunction(xsink, trgpgm->priv, name, new_name, inject);
2188 return pgm->priv->parseAddDomain(n_dom);
2192 return pgm.priv->dom;
2196 pgm.priv->dom |= n_dom;
2200 int64 rv = pgm.priv->pwo.parse_options;
2201 pgm.priv->pwo.parse_options = po;
2205 DLLLOCAL
static void makeParseWarning(
QoreProgram* pgm,
const QoreProgramLocation &loc,
int code,
2206 const char* warn,
const char* fmt, ...) {
2210 if (!pgm->priv->warnSink || !(code & pgm->priv->pwo.warn_mask)) {
2217 va_start(args, fmt);
2218 int rc = desc->
vsprintf(fmt, args);
2223 QoreException *ne =
new ParseException(loc, warn, desc);
2224 pgm->priv->warnSink->raiseException(ne);
2227 DLLLOCAL
static void makeParseWarning(
QoreProgram* pgm,
const QoreProgramLocation& loc,
int code,
2232 if (!pgm->priv->warnSink || !(code & pgm->priv->pwo.warn_mask)) {
2237 QoreException *ne =
new ParseException(loc, warn, desc);
2238 pgm->priv->warnSink->raiseException(ne);
2241 DLLLOCAL
static void exportGlobalVariable(
QoreProgram* pgm,
const char* name,
bool readonly,
QoreProgram* tpgm,
2243 pgm->priv->exportGlobalVariable(name, readonly, *(tpgm->priv), xsink);
2246 DLLLOCAL
void attachDebug(
const qore_debug_program_private* n_dpgm) {
2247 printd(5,
"qore_program_private::attachDebug(n_dpgm: %p), dpgm: %p\n", n_dpgm, dpgm);
2253 dpgm =
const_cast<qore_debug_program_private*
>(n_dpgm);
2254 printd(5,
"qore_program_private::attachDebug, dpgm: %p, pgm_data_map: size:%d, begin: %p, end: %p\n", dpgm,
2255 pgm_data_map.size(), pgm_data_map.begin(), pgm_data_map.end());
2256 for (
auto& i : pgm_data_map) {
2257 i.second->dbgPendingAttach();
2258 i.second->dbgBreak();
2262 DLLLOCAL
void detachDebug(
const qore_debug_program_private* n_dpgm) {
2263 printd(5,
"qore_program_private::detachDebug(n_dpgm: %p), dpgm: %p\n", n_dpgm, dpgm);
2266 assert(n_dpgm==dpgm);
2270 printd(5,
"qore_program_private::detachDebug, dpgm: %p, pgm_data_map: size:%d, begin: %p, end: %p\n", dpgm,
2271 pgm_data_map.size(), pgm_data_map.begin(), pgm_data_map.end());
2272 for (
auto& i : pgm_data_map) {
2273 i.second->dbgPendingDetach();
2279 DLLLOCAL
void onAttach(DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink);
2280 DLLLOCAL
void onDetach(DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink);
2281 DLLLOCAL
void onStep(
const StatementBlock* blockStatement,
const AbstractStatement* statement,
unsigned bkptId,
int& flow, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink);
2282 DLLLOCAL
void onFunctionEnter(
const StatementBlock* statement, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink);
2283 DLLLOCAL
void onFunctionExit(
const StatementBlock* statement,
QoreValue& returnValue, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink);
2284 DLLLOCAL
void onException(
const AbstractStatement* statement, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink);
2285 DLLLOCAL
void onExit(
const StatementBlock* statement,
QoreValue& returnValue, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink);
2287 DLLLOCAL
int breakProgramThread(
int tid) {
2288 printd(5,
"qore_program_private::breakProgramThread(), this: %p, tid: %d\n",
this,
q_gettid());
2290 for (
auto& i : pgm_data_map) {
2291 if (i.first->gettid() == tid) {
2292 i.second->dbgBreak();
2299 DLLLOCAL
void breakProgram() {
2300 printd(5,
"qore_program_private::breakProgram(), this: %p\n",
this);
2302 for (
auto& i : pgm_data_map) {
2303 i.second->dbgBreak();
2308 if (!bkpt ||
this == bkpt->pgm)
return;
2309 if (!checkAllowDebugging(xsink))
2315 breakpointList.push_back(bkpt);
2320 DLLLOCAL
void deleteAllBreakpoints() {
2322 for (QoreBreakpointList_t::iterator it = breakpointList.begin(); it != breakpointList.end(); ++it) {
2323 (*it)->unassignAllStatements();
2324 (*it)->pgm =
nullptr;
2327 breakpointList.clear();
2330 DLLLOCAL
void getBreakpoints(QoreBreakpointList_t &bkptList) {
2333 for (QoreBreakpointList_t::iterator it = breakpointList.begin(); it != breakpointList.end(); ++it) {
2334 bkptList.push_back(*it);
2339 DLLLOCAL
void getStatementBreakpoints(
const AbstractStatement* statement, QoreBreakpointList_t &bkptList) {
2342 if (statement->breakpoints) {
2343 for (std::list<QoreBreakpoint*>::iterator it = statement->breakpoints->begin(); it != statement->breakpoints->end(); ++it) {
2344 bkptList.push_back(*it);
2350 DLLLOCAL
inline unsigned onCheckBreakpoint(
const AbstractStatement* statement,
ExceptionSink* xsink) {
2360 DLLLOCAL
unsigned long getStatementId(
const AbstractStatement* statement)
const {
2364 ReverseStatementIdMap_t::const_iterator i = reverseStatementIds.find((AbstractStatement*) statement);
2365 if (i == reverseStatementIds.end())
2370 DLLLOCAL AbstractStatement* resolveStatementId(
unsigned long statementId)
const {
2372 if (statementId == 0 || statementId > statementIds.size())
2374 return statementIds[statementId-1];
2377 DLLLOCAL
unsigned getProgramId()
const {
2390 qore_root_ns_private::clearData(*RootNS, xsink);
2393 DLLLOCAL
static QoreProgram* resolveProgramId(
unsigned programId) {
2394 printd(5,
"qore_program_private::resolveProgramId(%x)\n", programId);
2396 for (qore_program_to_object_map_t::iterator i = qore_program_to_object_map.begin(); i != qore_program_to_object_map.end(); i++) {
2397 if (i->first->priv->programId == programId)
2406 xsink->
raiseException(
"DEBUGGING",
"program does not provide internal data for debugging");
2414 DLLLOCAL
void addStatementToIndexIntern(name_section_sline_statement_map_t* statementIndex,
const char* key, AbstractStatement* statement,
int offs,
const char* section,
int sectionOffs);
2415 DLLLOCAL
static void registerStatement(
QoreProgram* pgm, AbstractStatement* statement,
bool addToIndex);
2416 DLLLOCAL
QoreHashNode* getSourceIndicesIntern(name_section_sline_statement_map_t* statementIndex,
ExceptionSink* xsink)
const;
2418 return getSourceIndicesIntern(&statementByLabelIndex, xsink);
2421 return getSourceIndicesIntern(&statementByFileIndex, xsink);
2424 DLLLOCAL AbstractStatement* getStatementFromIndex(
const char* name,
int line) {
2425 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d), this: %p, file#: %d, label#: %d\n", name, line,
this, statementByFileIndex.size(), statementByLabelIndex.size());
2427 name_section_sline_statement_map_t::iterator it;
2428 if (statementByFileIndex.empty()) {
2431 bool addOffs =
true;
2432 if (!name || *name ==
'\0') {
2433 if (statementByFileIndex.size() != 1)
2435 it = statementByFileIndex.begin();
2437 size_t l = strlen(name);
2438 it = statementByFileIndex.find(name);
2439 if (it == statementByFileIndex.end()) {
2440 it = statementByLabelIndex.find(name);
2441 if (it == statementByLabelIndex.end()) {
2444 it = statementByFileIndex.begin();
2445 while (it != statementByFileIndex.end()) {
2446 size_t k = strlen(it->first);
2448 if (strcmp(name, it->first + k - l) == 0) {
2450 if (k == l || name[0] ==
'/' || it->first[k-l-1] ==
'/') {
2457 if (it == statementByFileIndex.end()) {
2458 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) no suffix match, this: %p\n", name, line,
this);
2461 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found by file suffix match, this: %p\n", name, line,
this);
2464 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found by label full match, this: %p\n", name, line,
this);
2467 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found by file full match, this: %p\n", name, line,
this);
2470 sline_statement_map_t *ssm = &it->second->statementMap;
2471 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found '%s', this: %p, ssm#: %d\n", name, line, it->first,
this, ssm->size());
2472 if (ssm->size() == 0)
2475 sline_statement_map_t::iterator li = ssm->upper_bound(line);
2476 if (li == ssm->begin()) {
2477 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) no statement found by line #1, this: %p\n", name, line,
this);
2483 AbstractStatement* st =
nullptr;
2486 if (ln != li->first) {
2490 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) {
2491 int n = li->second->loc->end_line - li->second->loc->start_line;
2504 if (li == ssm->begin())
2509 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);
2511 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) no statement found by line #2, this: %p\n", name, line,
this);
2517 printd(5,
"qore_program_private::registerQoreObject() pgm: %p, pgmid: %d\n", pgm, getProgramId());
2519 qore_program_to_object_map_t::iterator i = qore_program_private::qore_program_to_object_map.find(pgm);
2520 assert(i != qore_program_private::qore_program_to_object_map.end());
2521 if (i->second && i->second != o) {
2522 xsink->
raiseException(
"PROGRAM-ERROR",
"The Program has already assigned QoreObject");
2529 printd(5,
"qore_program_private::unregisterQoreObject() pgm: %p, pgmid: %d\n", pgm, getProgramId());
2531 qore_program_to_object_map_t::iterator i = qore_program_private::qore_program_to_object_map.find(pgm);
2532 assert(i != qore_program_private::qore_program_to_object_map.end());
2533 assert(i->second == o);
2534 i->second =
nullptr;
2539 qore_program_to_object_map_t::iterator i = qore_program_to_object_map.find(pgm);
2540 if (i == qore_program_to_object_map.end()) {
2550 DLLLOCAL
void deferCodeInitialization(DeferredCodeObject* o) {
2554 DLLLOCAL
void removeDeferredCode(DeferredCodeObject* o) {
2555 dset_t::iterator i = dset.find(o);
2556 if (i != dset.end()) {
2561 DLLLOCAL
int initDeferredCode();
2565 qore_program_to_object_map_t::iterator i = qore_program_to_object_map.find(pgm);
2566 assert(i != qore_program_to_object_map.end());
2568 printd(5,
"qore_program_private::getQoreObject() pgm: %p, pgmid: %d, second: %p\n", i->first, i->first->getProgramId(), i->second);
2572 printd(5,
"qore_program_private::getQoreObject() pgm: %p, pgmid: %d, new second: %p\n", pgm, pgm->
getProgramId(), i->second);
2582 qore_program_to_object_map_t::iterator i = qore_program_to_object_map.begin();
2583 while (i != qore_program_to_object_map.end()) {
2585 printd(5,
"qore_program_private::getAllQoreObjects() pgm: %p, pgmid: %d, second: %p\n", i->first, i->first->getProgramId(), i->second);
2589 printd(5,
"qore_program_private::getAllQoreObjects() pgm: %p, pgmid: %d, new second: %p\n", i->first, i->first->getProgramId(), i->second);
2592 (*l)->push(i->second,
nullptr);
2601 const AbstractQoreZoneInfo* n_TZ = QTZM.getLocalZoneInfo()) {
2609 if (!pendingParseSink)
2615 qore_debug_program_private* dpgm =
nullptr;
2617 QoreBreakpointList_t breakpointList;
2620 name_section_sline_statement_map_t statementByFileIndex;
2621 name_section_sline_statement_map_t statementByLabelIndex;
2624 typedef std::vector<AbstractStatement*> StatementVector_t;
2625 StatementVector_t statementIds;
2628 typedef std::map<AbstractStatement*, unsigned long> ReverseStatementIdMap_t;
2629 ReverseStatementIdMap_t reverseStatementIds;
2632 typedef std::set<DeferredCodeObject*> dset_t;
2641 DLLLOCAL qore_debug_program_private* getDebugProgram(AutoQoreCounterDec& ad) {
2644 qore_debug_program_private* ret = dpgm;
2653 DLLLOCAL
bool isBreakpointRegistered(
const QoreBreakpoint* bkpt)
const {
2654 return std::find(breakpointList.begin(), breakpointList.end(), bkpt) != breakpointList.end();
2658 typedef std::map<QoreProgram*, QoreObject*> qore_program_to_object_map_t;
2659 static qore_program_to_object_map_t qore_program_to_object_map;
2661 static volatile unsigned programIdCounter;
2665class ParseWarnHelper :
public ParseWarnOptions {
2669 DLLLOCAL ParseWarnHelper(
const ParseWarnOptions &new_opts) {
2671 restore = pgm ? qore_program_private::setSaveParseWarnOptions(pgm, new_opts, *
this) : false;
2673 DLLLOCAL ~ParseWarnHelper() {
2675 qore_program_private::setParseWarnOptions(
getProgram(), *
this);
2679typedef std::map<QoreProgram*, qore_program_private*> qore_program_map_t;
2682class qore_debug_program_private {
2684 DLLLOCAL qore_debug_program_private(
QoreDebugProgram* n_dpgm) : dpgm(n_dpgm) {}
2686 DLLLOCAL ~qore_debug_program_private() {
2687 assert(qore_program_map.empty());
2691 if (!pgm->priv->checkAllowDebugging(xsink))
2694 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2695 printd(5,
"qore_debug_program_private::addProgram(), this: %p, pgm: %p, i: %p, end: %p\n",
this, pgm, i,
2696 qore_program_map.end());
2697 if (i != qore_program_map.end())
2699 qore_program_map.insert(qore_program_map_t::value_type(pgm, pgm->priv));
2701 pgm->priv->attachDebug(
this);
2706 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2707 printd(5,
"qore_debug_program_private::removeProgram(), this: %p, pgm: %p, i: %p, end: %p\n",
this, pgm, i,
2708 qore_program_map.end());
2709 if (i == qore_program_map.end())
2711 pgm->priv->detachDebug(
this);
2712 qore_program_map.erase(i);
2717 DLLLOCAL
void removeAllPrograms() {
2719 printd(5,
"qore_debug_program_private::removeAllPrograms(), this: %p\n",
this);
2720 qore_program_map_t::iterator i;
2721 while ((i = qore_program_map.begin()) != qore_program_map.end()) {
2722 qore_program_private* qpp = i->second;
2724 qore_program_map.erase(i);
2725 qpp->detachDebug(
this);
2732 printd(5,
"qore_debug_program_private::getAllProgramObjects(), this: %p\n",
this);
2734 qore_program_map_t::iterator i = qore_program_map.begin();
2735 while (i != qore_program_map.end()) {
2738 (*l)->push(o,
nullptr);
2745 DLLLOCAL
void onAttach(
QoreProgram* pgm, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
2747 AutoQoreCounterDec ad(&debug_program_counter);
2748 dpgm->onAttach(pgm, rs, rts, xsink);
2751 DLLLOCAL
void onDetach(
QoreProgram* pgm, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
2753 AutoQoreCounterDec ad(&debug_program_counter);
2754 dpgm->onDetach(pgm, rs, rts, xsink);
2764 DLLLOCAL
void onStep(
QoreProgram* pgm,
const StatementBlock* blockStatement,
const AbstractStatement* statement,
2765 unsigned bkptId,
int& flow, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink) {
2766 AutoQoreCounterDec ad(&debug_program_counter);
2767 dpgm->onStep(pgm, blockStatement, statement, bkptId, flow, rs, rts, xsink);
2770 DLLLOCAL
void onFunctionEnter(
QoreProgram* pgm,
const StatementBlock* statement, DebugRunStateEnum& rs,
2772 AutoQoreCounterDec ad(&debug_program_counter);
2773 dpgm->onFunctionEnter(pgm, statement, rs, rts, xsink);
2779 DLLLOCAL
void onFunctionExit(
QoreProgram* pgm,
const StatementBlock* statement,
QoreValue& returnValue,
2780 DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink) {
2781 AutoQoreCounterDec ad(&debug_program_counter);
2782 dpgm->onFunctionExit(pgm, statement, returnValue, rs, rts, xsink);
2787 DLLLOCAL
void onException(
QoreProgram* pgm,
const AbstractStatement* statement, DebugRunStateEnum& rs,
2789 AutoQoreCounterDec ad(&debug_program_counter);
2790 dpgm->onException(pgm, statement, rs, rts, xsink);
2795 DLLLOCAL
void onExit(
QoreProgram* pgm,
const StatementBlock* statement,
QoreValue& returnValue,
2796 DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink) {
2797 AutoQoreCounterDec ad(&debug_program_counter);
2798 dpgm->onExit(pgm, statement, returnValue, rs, rts, xsink);
2801 DLLLOCAL
int breakProgramThread(
QoreProgram* pgm,
int tid) {
2808 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2809 printd(5,
"qore_debug_program_private::breakProgramThread(), this: %p, pgm: %p, i: %p, end: %p, tid: %d\n",
2810 this, pgm, i, qore_program_map.end(), tid);
2811 if (i == qore_program_map.end())
2813 if (i->second->breakProgramThread(tid))
2825 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2826 printd(5,
"qore_debug_program_private::breakProgram(), this: %p, pgm: %p, i: %p, end: %p\n",
this, pgm, i,
2827 qore_program_map.end());
2828 if (i == qore_program_map.end())
2830 i->second->breakProgram();
2834 DLLLOCAL
void waitForTerminationAndClear(
ExceptionSink* xsink) {
2835 removeAllPrograms();
2840 DLLLOCAL
int getInterruptedCount() {
2841 return debug_program_counter.
getCount();
2848 qore_program_map_t qore_program_map;
DLLEXPORT const QoreEncoding * QCS_DEFAULT
the default encoding for the Qore library
DLLEXPORT char * q_basenameptr(const char *path)
returns a pointer within the same string
#define PO_NO_LOCALE_CONTROL
do not allow changes to program locale
Definition Restrictions.h:64
#define PO_NO_CHILD_PO_RESTRICTIONS
turn off parse option inheritance restrictions
Definition Restrictions.h:51
#define PO_ALLOW_INJECTION
allow code injection
Definition Restrictions.h:76
#define PO_POSITIVE_OPTIONS
mask of all options allowing for more freedom (instead of less)
Definition Restrictions.h:136
#define PO_FREE_OPTIONS
mask of options that have no effect on code access or code safety
Definition Restrictions.h:140
#define PO_NO_DEBUGGING
disallows debugging actions that could be insecure such as reading the thread local variable stack
Definition Restrictions.h:86
DLLLOCAL void ref() const
increments the reference count of the object
Definition AbstractPrivateData.h:51
DLLEXPORT void deref(ExceptionSink *xsink)
decrements the reference count and calls derefImpl() if there_can_be_only_one is false,...
an abstract class for program-specific external data
Definition QoreProgram.h:1001
provides a safe and exception-safe way to hold locks in Qore, only to be used on the stack,...
Definition QoreThreadLock.h:136
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition ExceptionSink.h:50
DLLEXPORT void assimilate(ExceptionSink *xs)
assimilates all entries of the "xs" argument by appending them to the internal list and deletes the "...
DLLEXPORT AbstractQoreNode * raiseException(const char *err, const char *fmt,...)
appends a Qore-language exception to the list
DLLEXPORT AbstractQoreNode * raiseErrnoException(const char *err, int en, const char *fmt,...)
appends a Qore-language exception to the list and appends the result of strerror(errno) to the descri...
DLLEXPORT void clear()
deletes the exception list immediately
DLLEXPORT bool isException() const
returns true if at least one exception is present
provides a safe and exception-safe way to hold read locks in Qore, only to be used on the stack,...
Definition QoreRWLock.h:104
provides a safe and exception-safe way to hold write locks in Qore, only to be used on the stack,...
Definition QoreRWLock.h:143
Class implementing breakpoint for debugging.
Definition QoreProgram.h:1040
DLLEXPORT unsigned getBreakpointId() const
get the breakpoint id
DLLEXPORT void assignProgram(QoreProgram *new_pgm, ExceptionSink *xsink)
defines a Qore-language class
Definition QoreClass.h:310
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:41
DLLEXPORT int getCount() const
returns the current count
DLLEXPORT int waitForZero(ExceptionSink *xsink, int timeout_ms=0)
blocks the calling thread until the counter reaches 0
supports parsing and executing Qore-language code, reference counted, dynamically-allocated only
Definition QoreDebugProgram.h:66
This is the hash or associative list container type in Qore, dynamically allocated only,...
Definition QoreHashNode.h:51
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:61
supports parsing and executing Qore-language code, reference counted, dynamically-allocated only
Definition QoreProgram.h:128
static DLLEXPORT QoreObject * getQoreObject(QoreProgram *pgm)
get QoreObject of QoreProgram
DLLEXPORT unsigned getProgramId() const
get the program id
virtual DLLEXPORT void deref(ExceptionSink *xsink)
decrements the reference count of the object
provides a simple POSIX-threads-based read-write lock
Definition QoreRWLock.h:47
Provides atomic reference counting to Qore objects.
Definition QoreReferenceCounter.h:44
DLLEXPORT void ROreference() const
Atomically increments the reference count.
DLLEXPORT int reference_count() const
Gets the reference count.
DLLEXPORT bool ROdereference() const
Atomically decrements the reference count.
abstract base class for c++ Exceptions in the Qore library
Definition QoreStandardException.h:49
Qore's string type supported by the QoreEncoding class.
Definition QoreString.h:93
DLLEXPORT const char * c_str() const
returns the string's buffer; this data should not be changed
DLLEXPORT size_t strlen() const
returns number of bytes in the string (not including the null pointer)
DLLEXPORT bool empty() const
returns true if the string is empty, false if not
DLLEXPORT int vsprintf(const char *fmt, va_list args)
this will concatentate a formatted string to the existing string according to the format string and t...
Qore's string value type, reference counted, dynamically-allocated only.
Definition QoreStringNode.h:50
provides access to thread-local storage
Definition QoreThreadLocalStorage.h:49
DLLLOCAL void set(T *ptr)
sets the key's value
Definition QoreThreadLocalStorage.h:77
DLLLOCAL T * get()
retrieves the key's value
Definition QoreThreadLocalStorage.h:72
provides a mutually-exclusive thread lock
Definition QoreThreadLock.h:49
a templated class to manage a reference count of an object that can throw a Qore-language exception w...
Definition ReferenceHolder.h:52
base class for resolved call references
Definition CallReferenceNode.h:115
the root namespace of a QoreProgram object
Definition QoreNamespace.h:397
Helps dereference values outside of locks.
Definition QoreLibIntern.h:554
DLLLOCAL void add(QoreValue v)
adds a value for dereferencing on exit
Definition QoreLibIntern.h:579
provides an exception-safe way to manage locks in Qore, only to be used on the stack,...
Definition QoreThreadLock.h:228
Private data for the Qore::StreamReader class.
Definition StreamReader.h:45
Private data for the Qore::StreamWriter class.
Definition StreamWriter.h:43
use this class to manage strings where the character encoding must be specified and may be different ...
Definition QoreString.h:1198
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:1239
typed hash declaration
Definition TypedHashDecl.h:44
holds an object and dereferences it in the destructor
Definition QoreValue.h:487
non-thread-safe vector for storing "char*" that you want to delete
Definition common.h:244
std::set< int > int_set_t
set of integers
Definition common.h:88
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:266
DLLEXPORT QoreProgram * getProgram()
returns the current QoreProgram
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:279