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(
ExceptionSink* xsink,
const char* name,
bool readonly,
1796 qore_program_private& tpgm,
const char* import_as =
nullptr);
1803 DLLLOCAL
void setThreadTZ(ThreadProgramData* tpd,
const AbstractQoreZoneInfo* tz) {
1805 pgm_data_map_t::iterator i = pgm_data_map.find(tpd);
1806 assert(i != pgm_data_map.end());
1807 i->second->setTZ(tz);
1810 DLLLOCAL
const AbstractQoreZoneInfo* getThreadTZ(ThreadProgramData* tpd,
bool& set)
const {
1812 pgm_data_map_t::const_iterator i = pgm_data_map.find(tpd);
1813 assert(i != pgm_data_map.end());
1814 set = i->second->tz_set;
1815 return i->second->tz;
1818 DLLLOCAL
void clearThreadTZ(ThreadProgramData* tpd) {
1820 pgm_data_map_t::iterator i = pgm_data_map.find(tpd);
1821 assert(i != pgm_data_map.end());
1822 i->second->clearTZ();
1825 DLLLOCAL
void addStatement(AbstractStatement* s);
1829 return parseExpression(source, label, xsink);
1833 ProgramThreadCountContextHelper pch(xsink, pgm,
true);
1837 if (exp_set.find(exp) == exp_set.end()) {
1838 xsink->
raiseException(
"INVALID-EXPRESSION",
"expression not registered to this Program object");
1841 ThreadFrameBoundaryHelper tfbh(
true);
1847 return rv.release();
1850 DLLLOCAL
void deleteExpression(q_exp_t exp) {
1852 q_exp_set_t::iterator i = exp_set.find(exp);
1853 if (i != exp_set.end()) {
1859 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);
1861 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);
1863 DLLLOCAL
const char* addString(
const char* str) {
1864 str_set_t::iterator i = str_set.lower_bound(str);
1865 if (i == str_set.end() || strcmp(*i, str)) {
1866 str_vec.push_back(strdup(str));
1867 i = str_set.insert(i, str_vec.back());
1872 DLLLOCAL
void addFile(
const char*& file) {
1873 file = addString(file);
1874 printd(5,
"qore_program_private::addFile('%s')\n", file);
1875 addStatementToIndexIntern(&statementByFileIndex, file,
nullptr, -1,
nullptr, -1);
1878 DLLLOCAL
void addFile(
const char*& file,
const char*& source,
int offset) {
1879 file = addString(file);
1881 source = addString(source);
1883 printd(5,
"qore_program_private::addFile('%s', '%s', %d)\n", file, source ? source :
"(null)", offset);
1884 addStatementToIndexIntern(&statementByFileIndex, file,
nullptr, -1, source, offset);
1886 addStatementToIndexIntern(&statementByLabelIndex, source,
nullptr, -1, file, offset);
1890 DLLLOCAL
int addFeature(
const char* f) {
1892 strset_t::iterator i = featureList.lower_bound(f);
1893 if (i != featureList.end() && (*i == f)) {
1897 featureList.insert(i, f);
1901 DLLLOCAL
void removeFeature(
const char* f) {
1902 strset_t::iterator i = featureList.find(f);
1903 assert(i != featureList.end());
1904 featureList.erase(i);
1907 DLLLOCAL
int addUserFeature(
const char* f) {
1909 strset_t::iterator i = userFeatureList.lower_bound(f);
1910 if (i != userFeatureList.end() && (*i == f)) {
1914 userFeatureList.insert(i, f);
1918 DLLLOCAL
bool hasUserFeature(
const std::string feature)
const {
1919 return userFeatureList.find(feature) != userFeatureList.end();
1922 DLLLOCAL
void removeUserFeature(
const char* f) {
1923 strset_t::iterator i = userFeatureList.find(f);
1924 assert(i != userFeatureList.end());
1925 userFeatureList.erase(i);
1928 DLLLOCAL
bool hasFeature(
const char* f)
const {
1929 return (featureList.find(f) != featureList.end())
1930 || (userFeatureList.find(f) != userFeatureList.end());
1933 DLLLOCAL
void runtimeImportSystemClassesIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1934 DLLLOCAL
void runtimeImportSystemConstantsIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1935 DLLLOCAL
void runtimeImportSystemFunctionsIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1936 DLLLOCAL
void runtimeImportSystemHashDeclsIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1938 DLLLOCAL
void runtimeImportSystemClasses(
ExceptionSink* xsink);
1939 DLLLOCAL
void runtimeImportSystemConstants(
ExceptionSink* xsink);
1940 DLLLOCAL
void runtimeImportSystemFunctions(
ExceptionSink* xsink);
1941 DLLLOCAL
void runtimeImportSystemHashDecls(
ExceptionSink* xsink);
1950 assert(extmap.find(owner) == extmap.end());
1951 extmap.insert(extmap_t::value_type(owner, pud));
1956 extmap_t::const_iterator i = extmap.find(owner);
1957 return i == extmap.end() ? nullptr : i->second;
1962 extmap_t::iterator i = extmap.find(owner);
1963 if (i == extmap.end()) {
1972 return qore_root_ns_private::getGlobalVars(*RootNS);
1975 DLLLOCAL LocalVar* createLocalVar(
const char* name,
const QoreTypeInfo* typeInfo);
1977 DLLLOCAL
const AbstractQoreFunctionVariant* runtimeFindCall(
const char* name,
const QoreListNode* params,
ExceptionSink* xsink);
1982 return pgm.priv->runtimeFindClass(class_name, xsink);
1986 pgm.priv->doThreadInit(xsink);
1991 if (!pgm.priv->exec_class) {
1992 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>))");
1995 pgm.priv->exec_class_rv.discard(xsink);
1996 pgm.priv->exec_class_rv = rv.release();
2002 return pgm.priv->preregisterNewThread(xsink);
2006 DLLLOCAL
static void cancelPreregistration(
QoreProgram& pgm) {
2007 pgm.priv->cancelPreregistration();
2011 DLLLOCAL
static void registerNewThread(
QoreProgram& pgm,
int tid) {
2012 pgm.priv->registerNewThread(tid);
2016 pgm.priv->runtimeImportSystemClasses(xsink);
2020 pgm.priv->runtimeImportSystemHashDecls(xsink);
2024 pgm.priv->runtimeImportSystemConstants(xsink);
2028 pgm.priv->runtimeImportSystemFunctions(xsink);
2032 pgm.priv->runtimeImportSystemApi(xsink);
2035 DLLLOCAL
static qore_program_private* get(
QoreProgram& pgm) {
2040 pgm.priv->clearThreadData(xsink);
2043 DLLLOCAL
static void addStatement(
QoreProgram& pgm, AbstractStatement* s) {
2044 pgm.priv->addStatement(s);
2047 DLLLOCAL
static const AbstractQoreZoneInfo* currentTZIntern(
QoreProgram& pgm) {
2048 return pgm.priv->TZ;
2052 return pgm.priv->lockParsing(xsink);
2055 DLLLOCAL
static void unlockParsing(
QoreProgram& pgm) {
2056 pgm.priv->unlockParsing();
2060 return pgm.priv->incThreadCount(xsink);
2063 DLLLOCAL
static void decThreadCount(
QoreProgram& pgm,
int tid) {
2064 pgm.priv->decThreadCount(tid);
2068 DLLLOCAL
static void addSignal(
QoreProgram& pgm,
int sig) {
2069 assert(pgm.priv->sigset.find(sig) == pgm.priv->sigset.end());
2070 pgm.priv->sigset.insert(sig);
2074 DLLLOCAL
static void delSignal(
QoreProgram& pgm,
int sig) {
2075 assert(pgm.priv->sigset.find(sig) != pgm.priv->sigset.end());
2076 pgm.priv->sigset.erase(sig);
2080 pgm.priv->qore_program_private_base::startThread(xsink);
2085 return pgm.priv->setThreadInit(n_thr_init, xsink);
2090 return pgm->priv->runtimeGetCallReference(name, xsink);
2093 DLLLOCAL
static const ParseWarnOptions& getParseWarnOptions(
const QoreProgram* pgm) {
2094 return pgm->priv->pwo;
2097 DLLLOCAL
static bool setSaveParseWarnOptions(
const QoreProgram* pgm,
const ParseWarnOptions &new_opts,
2098 ParseWarnOptions &old_opts) {
2099 if (new_opts == pgm->priv->pwo)
2101 old_opts = pgm->priv->pwo;
2102 pgm->priv->pwo = new_opts;
2106 DLLLOCAL
static void setParseWarnOptions(
const QoreProgram* pgm,
const ParseWarnOptions &new_opts) {
2107 pgm->priv->pwo = new_opts;
2110 DLLLOCAL
static bool setThreadVarData(
QoreProgram* pgm, ThreadProgramData* td, ThreadLocalProgramData* &tlpd,
2112 return pgm->priv->setThreadVarData(td, tlpd, run);
2116 pgm->priv->makeParseException(loc,
"PARSE-EXCEPTION", desc);
2119 DLLLOCAL
static void makeParseException(
QoreProgram* pgm,
const QoreProgramLocation &loc,
const char* err,
2121 pgm->priv->makeParseException(loc, err, desc);
2126 return pgm->priv->getDefine(name, is_defined);
2129 DLLLOCAL
static const QoreValue parseGetDefine(
QoreProgram* pgm,
const char* name,
bool& is_defined) {
2130 return pgm->priv->getDefine(name, is_defined);
2135 return pgm->priv->runTimeGetDefine(name, is_defined);
2138 DLLLOCAL
static QoreValue runTimeGetDefine(
QoreProgram* pgm,
const char* name,
bool& is_defined) {
2139 return pgm->priv->runTimeGetDefine(name, is_defined);
2143 return pgm->priv->runTimeGetAllDefines();
2146 DLLLOCAL
static bool parseUnDefine(
QoreProgram* pgm,
const char* name) {
2147 return pgm->priv->parseUnDefine(name);
2151 return pgm->priv->runTimeUnDefine(name, xsink);
2154 DLLLOCAL
static bool parseIsDefined(
QoreProgram* pgm,
const char* name) {
2155 return pgm->priv->isDefined(name);
2158 DLLLOCAL
static bool runTimeIsDefined(
QoreProgram* pgm,
const char* name) {
2159 return pgm->priv->runTimeIsDefined(name);
2162 DLLLOCAL
static void parseDefine(
QoreProgram* pgm,
const QoreProgramLocation* loc,
const char* str,
2164 pgm->priv->parseDefine(loc, str, val);
2168 pgm->priv->runTimeDefine(str, val, xsink);
2172 const QoreProgramLocation* loc =
nullptr) {
2174 pgm->priv->addParseException(*xsink, loc);
2179 const QoreProgramLocation* loc =
nullptr) {
2180 pgm->priv->addParseException(xsink, loc);
2184 const char* name,
const char* new_name =
nullptr,
bool inject =
false) {
2185 srcpgm->priv->exportFunction(xsink, trgpgm->priv, name, new_name, inject);
2189 return pgm->priv->parseAddDomain(n_dom);
2193 return pgm.priv->dom;
2197 pgm.priv->dom |= n_dom;
2201 int64 rv = pgm.priv->pwo.parse_options;
2202 pgm.priv->pwo.parse_options = po;
2206 DLLLOCAL
static void makeParseWarning(
QoreProgram* pgm,
const QoreProgramLocation &loc,
int code,
2207 const char* warn,
const char* fmt, ...) {
2211 if (!pgm->priv->warnSink || !(code & pgm->priv->pwo.warn_mask)) {
2218 va_start(args, fmt);
2219 int rc = desc->
vsprintf(fmt, args);
2224 QoreException *ne =
new ParseException(loc, warn, desc);
2225 pgm->priv->warnSink->raiseException(ne);
2228 DLLLOCAL
static void makeParseWarning(
QoreProgram* pgm,
const QoreProgramLocation& loc,
int code,
2233 if (!pgm->priv->warnSink || !(code & pgm->priv->pwo.warn_mask)) {
2238 QoreException *ne =
new ParseException(loc, warn, desc);
2239 pgm->priv->warnSink->raiseException(ne);
2242 DLLLOCAL
void attachDebug(
const qore_debug_program_private* n_dpgm) {
2243 printd(5,
"qore_program_private::attachDebug(n_dpgm: %p), dpgm: %p\n", n_dpgm, dpgm);
2249 dpgm =
const_cast<qore_debug_program_private*
>(n_dpgm);
2250 printd(5,
"qore_program_private::attachDebug, dpgm: %p, pgm_data_map: size:%d, begin: %p, end: %p\n", dpgm,
2251 pgm_data_map.size(), pgm_data_map.begin(), pgm_data_map.end());
2252 for (
auto& i : pgm_data_map) {
2253 i.second->dbgPendingAttach();
2254 i.second->dbgBreak();
2258 DLLLOCAL
void detachDebug(
const qore_debug_program_private* n_dpgm) {
2259 printd(5,
"qore_program_private::detachDebug(n_dpgm: %p), dpgm: %p\n", n_dpgm, dpgm);
2262 assert(n_dpgm==dpgm);
2266 printd(5,
"qore_program_private::detachDebug, dpgm: %p, pgm_data_map: size:%d, begin: %p, end: %p\n", dpgm,
2267 pgm_data_map.size(), pgm_data_map.begin(), pgm_data_map.end());
2268 for (
auto& i : pgm_data_map) {
2269 i.second->dbgPendingDetach();
2275 DLLLOCAL
void onAttach(DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink);
2276 DLLLOCAL
void onDetach(DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink);
2277 DLLLOCAL
void onStep(
const StatementBlock* blockStatement,
const AbstractStatement* statement,
unsigned bkptId,
int& flow, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink);
2278 DLLLOCAL
void onFunctionEnter(
const StatementBlock* statement, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink);
2279 DLLLOCAL
void onFunctionExit(
const StatementBlock* statement,
QoreValue& returnValue, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink);
2280 DLLLOCAL
void onException(
const AbstractStatement* statement, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink);
2281 DLLLOCAL
void onExit(
const StatementBlock* statement,
QoreValue& returnValue, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink);
2283 DLLLOCAL
int breakProgramThread(
int tid) {
2284 printd(5,
"qore_program_private::breakProgramThread(), this: %p, tid: %d\n",
this,
q_gettid());
2286 for (
auto& i : pgm_data_map) {
2287 if (i.first->gettid() == tid) {
2288 i.second->dbgBreak();
2295 DLLLOCAL
void breakProgram() {
2296 printd(5,
"qore_program_private::breakProgram(), this: %p\n",
this);
2298 for (
auto& i : pgm_data_map) {
2299 i.second->dbgBreak();
2304 if (!bkpt ||
this == bkpt->pgm)
return;
2305 if (!checkAllowDebugging(xsink))
2311 breakpointList.push_back(bkpt);
2316 DLLLOCAL
void deleteAllBreakpoints() {
2318 for (QoreBreakpointList_t::iterator it = breakpointList.begin(); it != breakpointList.end(); ++it) {
2319 (*it)->unassignAllStatements();
2320 (*it)->pgm =
nullptr;
2323 breakpointList.clear();
2326 DLLLOCAL
void getBreakpoints(QoreBreakpointList_t &bkptList) {
2329 for (QoreBreakpointList_t::iterator it = breakpointList.begin(); it != breakpointList.end(); ++it) {
2330 bkptList.push_back(*it);
2335 DLLLOCAL
void getStatementBreakpoints(
const AbstractStatement* statement, QoreBreakpointList_t &bkptList) {
2338 if (statement->breakpoints) {
2339 for (std::list<QoreBreakpoint*>::iterator it = statement->breakpoints->begin(); it != statement->breakpoints->end(); ++it) {
2340 bkptList.push_back(*it);
2346 DLLLOCAL
inline unsigned onCheckBreakpoint(
const AbstractStatement* statement,
ExceptionSink* xsink) {
2356 DLLLOCAL
unsigned long getStatementId(
const AbstractStatement* statement)
const {
2360 ReverseStatementIdMap_t::const_iterator i = reverseStatementIds.find((AbstractStatement*) statement);
2361 if (i == reverseStatementIds.end())
2366 DLLLOCAL AbstractStatement* resolveStatementId(
unsigned long statementId)
const {
2368 if (statementId == 0 || statementId > statementIds.size())
2370 return statementIds[statementId-1];
2373 DLLLOCAL
unsigned getProgramId()
const {
2386 qore_root_ns_private::clearData(*RootNS, xsink);
2389 DLLLOCAL
static QoreProgram* resolveProgramId(
unsigned programId) {
2390 printd(5,
"qore_program_private::resolveProgramId(%x)\n", programId);
2392 for (qore_program_to_object_map_t::iterator i = qore_program_to_object_map.begin(); i != qore_program_to_object_map.end(); i++) {
2393 if (i->first->priv->programId == programId)
2402 xsink->
raiseException(
"DEBUGGING",
"program does not provide internal data for debugging");
2410 DLLLOCAL
void addStatementToIndexIntern(name_section_sline_statement_map_t* statementIndex,
const char* key, AbstractStatement* statement,
int offs,
const char* section,
int sectionOffs);
2411 DLLLOCAL
static void registerStatement(
QoreProgram* pgm, AbstractStatement* statement,
bool addToIndex);
2412 DLLLOCAL
QoreHashNode* getSourceIndicesIntern(name_section_sline_statement_map_t* statementIndex,
ExceptionSink* xsink)
const;
2414 return getSourceIndicesIntern(&statementByLabelIndex, xsink);
2417 return getSourceIndicesIntern(&statementByFileIndex, xsink);
2420 DLLLOCAL AbstractStatement* getStatementFromIndex(
const char* name,
int line) {
2421 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d), this: %p, file#: %d, label#: %d\n", name, line,
this, statementByFileIndex.size(), statementByLabelIndex.size());
2423 name_section_sline_statement_map_t::iterator it;
2424 if (statementByFileIndex.empty()) {
2427 bool addOffs =
true;
2428 if (!name || *name ==
'\0') {
2429 if (statementByFileIndex.size() != 1)
2431 it = statementByFileIndex.begin();
2433 size_t l = strlen(name);
2434 it = statementByFileIndex.find(name);
2435 if (it == statementByFileIndex.end()) {
2436 it = statementByLabelIndex.find(name);
2437 if (it == statementByLabelIndex.end()) {
2440 it = statementByFileIndex.begin();
2441 while (it != statementByFileIndex.end()) {
2442 size_t k = strlen(it->first);
2444 if (strcmp(name, it->first + k - l) == 0) {
2446 if (k == l || name[0] ==
'/' || it->first[k-l-1] ==
'/') {
2453 if (it == statementByFileIndex.end()) {
2454 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) no suffix match, this: %p\n", name, line,
this);
2457 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found by file suffix match, this: %p\n", name, line,
this);
2460 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found by label full match, this: %p\n", name, line,
this);
2463 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found by file full match, this: %p\n", name, line,
this);
2466 sline_statement_map_t *ssm = &it->second->statementMap;
2467 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) found '%s', this: %p, ssm#: %d\n", name, line, it->first,
this, ssm->size());
2468 if (ssm->size() == 0)
2471 sline_statement_map_t::iterator li = ssm->upper_bound(line);
2472 if (li == ssm->begin()) {
2473 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) no statement found by line #1, this: %p\n", name, line,
this);
2479 AbstractStatement* st =
nullptr;
2482 if (ln != li->first) {
2486 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) {
2487 int n = li->second->loc->end_line - li->second->loc->start_line;
2500 if (li == ssm->begin())
2505 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);
2507 printd(5,
"qore_program_private::getStatementFromIndex('%s',%d) no statement found by line #2, this: %p\n", name, line,
this);
2513 printd(5,
"qore_program_private::registerQoreObject() pgm: %p, pgmid: %d\n", pgm, getProgramId());
2515 qore_program_to_object_map_t::iterator i = qore_program_private::qore_program_to_object_map.find(pgm);
2516 assert(i != qore_program_private::qore_program_to_object_map.end());
2517 if (i->second && i->second != o) {
2518 xsink->
raiseException(
"PROGRAM-ERROR",
"The Program has already assigned QoreObject");
2525 printd(5,
"qore_program_private::unregisterQoreObject() pgm: %p, pgmid: %d\n", pgm, getProgramId());
2527 qore_program_to_object_map_t::iterator i = qore_program_private::qore_program_to_object_map.find(pgm);
2528 assert(i != qore_program_private::qore_program_to_object_map.end());
2529 assert(i->second == o);
2530 i->second =
nullptr;
2535 qore_program_to_object_map_t::iterator i = qore_program_to_object_map.find(pgm);
2536 if (i == qore_program_to_object_map.end()) {
2546 DLLLOCAL
void deferCodeInitialization(DeferredCodeObject* o) {
2550 DLLLOCAL
void removeDeferredCode(DeferredCodeObject* o) {
2551 dset_t::iterator i = dset.find(o);
2552 if (i != dset.end()) {
2557 DLLLOCAL
int initDeferredCode();
2561 qore_program_to_object_map_t::iterator i = qore_program_to_object_map.find(pgm);
2562 assert(i != qore_program_to_object_map.end());
2564 printd(5,
"qore_program_private::getQoreObject() pgm: %p, pgmid: %d, second: %p\n", i->first, i->first->getProgramId(), i->second);
2568 printd(5,
"qore_program_private::getQoreObject() pgm: %p, pgmid: %d, new second: %p\n", pgm, pgm->
getProgramId(), i->second);
2578 qore_program_to_object_map_t::iterator i = qore_program_to_object_map.begin();
2579 while (i != qore_program_to_object_map.end()) {
2581 printd(5,
"qore_program_private::getAllQoreObjects() pgm: %p, pgmid: %d, second: %p\n", i->first, i->first->getProgramId(), i->second);
2585 printd(5,
"qore_program_private::getAllQoreObjects() pgm: %p, pgmid: %d, new second: %p\n", i->first, i->first->getProgramId(), i->second);
2588 (*l)->push(i->second,
nullptr);
2597 const AbstractQoreZoneInfo* n_TZ = QTZM.getLocalZoneInfo()) {
2605 if (!pendingParseSink)
2611 qore_debug_program_private* dpgm =
nullptr;
2613 QoreBreakpointList_t breakpointList;
2616 name_section_sline_statement_map_t statementByFileIndex;
2617 name_section_sline_statement_map_t statementByLabelIndex;
2620 typedef std::vector<AbstractStatement*> StatementVector_t;
2621 StatementVector_t statementIds;
2624 typedef std::map<AbstractStatement*, unsigned long> ReverseStatementIdMap_t;
2625 ReverseStatementIdMap_t reverseStatementIds;
2628 typedef std::set<DeferredCodeObject*> dset_t;
2637 DLLLOCAL qore_debug_program_private* getDebugProgram(AutoQoreCounterDec& ad) {
2640 qore_debug_program_private* ret = dpgm;
2649 DLLLOCAL
bool isBreakpointRegistered(
const QoreBreakpoint* bkpt)
const {
2650 return std::find(breakpointList.begin(), breakpointList.end(), bkpt) != breakpointList.end();
2654 typedef std::map<QoreProgram*, QoreObject*> qore_program_to_object_map_t;
2655 static qore_program_to_object_map_t qore_program_to_object_map;
2657 static volatile unsigned programIdCounter;
2661class ParseWarnHelper :
public ParseWarnOptions {
2665 DLLLOCAL ParseWarnHelper(
const ParseWarnOptions &new_opts) {
2667 restore = pgm ? qore_program_private::setSaveParseWarnOptions(pgm, new_opts, *
this) : false;
2669 DLLLOCAL ~ParseWarnHelper() {
2671 qore_program_private::setParseWarnOptions(
getProgram(), *
this);
2675typedef std::map<QoreProgram*, qore_program_private*> qore_program_map_t;
2678class qore_debug_program_private {
2680 DLLLOCAL qore_debug_program_private(
QoreDebugProgram* n_dpgm) : dpgm(n_dpgm) {}
2682 DLLLOCAL ~qore_debug_program_private() {
2683 assert(qore_program_map.empty());
2687 if (!pgm->priv->checkAllowDebugging(xsink))
2690 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2691 printd(5,
"qore_debug_program_private::addProgram(), this: %p, pgm: %p, i: %p, end: %p\n",
this, pgm, i,
2692 qore_program_map.end());
2693 if (i != qore_program_map.end())
2695 qore_program_map.insert(qore_program_map_t::value_type(pgm, pgm->priv));
2697 pgm->priv->attachDebug(
this);
2702 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2703 printd(5,
"qore_debug_program_private::removeProgram(), this: %p, pgm: %p, i: %p, end: %p\n",
this, pgm, i,
2704 qore_program_map.end());
2705 if (i == qore_program_map.end())
2707 pgm->priv->detachDebug(
this);
2708 qore_program_map.erase(i);
2713 DLLLOCAL
void removeAllPrograms() {
2715 printd(5,
"qore_debug_program_private::removeAllPrograms(), this: %p\n",
this);
2716 qore_program_map_t::iterator i;
2717 while ((i = qore_program_map.begin()) != qore_program_map.end()) {
2718 qore_program_private* qpp = i->second;
2720 qore_program_map.erase(i);
2721 qpp->detachDebug(
this);
2728 printd(5,
"qore_debug_program_private::getAllProgramObjects(), this: %p\n",
this);
2730 qore_program_map_t::iterator i = qore_program_map.begin();
2731 while (i != qore_program_map.end()) {
2734 (*l)->push(o,
nullptr);
2741 DLLLOCAL
void onAttach(
QoreProgram* pgm, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
2743 AutoQoreCounterDec ad(&debug_program_counter);
2744 dpgm->onAttach(pgm, rs, rts, xsink);
2747 DLLLOCAL
void onDetach(
QoreProgram* pgm, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
2749 AutoQoreCounterDec ad(&debug_program_counter);
2750 dpgm->onDetach(pgm, rs, rts, xsink);
2760 DLLLOCAL
void onStep(
QoreProgram* pgm,
const StatementBlock* blockStatement,
const AbstractStatement* statement,
2761 unsigned bkptId,
int& flow, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink) {
2762 AutoQoreCounterDec ad(&debug_program_counter);
2763 dpgm->onStep(pgm, blockStatement, statement, bkptId, flow, rs, rts, xsink);
2766 DLLLOCAL
void onFunctionEnter(
QoreProgram* pgm,
const StatementBlock* statement, DebugRunStateEnum& rs,
2768 AutoQoreCounterDec ad(&debug_program_counter);
2769 dpgm->onFunctionEnter(pgm, statement, rs, rts, xsink);
2775 DLLLOCAL
void onFunctionExit(
QoreProgram* pgm,
const StatementBlock* statement,
QoreValue& returnValue,
2776 DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink) {
2777 AutoQoreCounterDec ad(&debug_program_counter);
2778 dpgm->onFunctionExit(pgm, statement, returnValue, rs, rts, xsink);
2783 DLLLOCAL
void onException(
QoreProgram* pgm,
const AbstractStatement* statement, DebugRunStateEnum& rs,
2785 AutoQoreCounterDec ad(&debug_program_counter);
2786 dpgm->onException(pgm, statement, rs, rts, xsink);
2791 DLLLOCAL
void onExit(
QoreProgram* pgm,
const StatementBlock* statement,
QoreValue& returnValue,
2792 DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink) {
2793 AutoQoreCounterDec ad(&debug_program_counter);
2794 dpgm->onExit(pgm, statement, returnValue, rs, rts, xsink);
2797 DLLLOCAL
int breakProgramThread(
QoreProgram* pgm,
int tid) {
2804 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2805 printd(5,
"qore_debug_program_private::breakProgramThread(), this: %p, pgm: %p, i: %p, end: %p, tid: %d\n",
2806 this, pgm, i, qore_program_map.end(), tid);
2807 if (i == qore_program_map.end())
2809 if (i->second->breakProgramThread(tid))
2821 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2822 printd(5,
"qore_debug_program_private::breakProgram(), this: %p, pgm: %p, i: %p, end: %p\n",
this, pgm, i,
2823 qore_program_map.end());
2824 if (i == qore_program_map.end())
2826 i->second->breakProgram();
2830 DLLLOCAL
void waitForTerminationAndClear(
ExceptionSink* xsink) {
2831 removeAllPrograms();
2836 DLLLOCAL
int getInterruptedCount() {
2837 return debug_program_counter.
getCount();
2844 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:128
provides a safe and exception-safe way to hold write locks in Qore, only to be used on the stack,...
Definition QoreRWLock.h:167
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