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"
60typedef vector_map_t<int, unsigned> ptid_map_t;
63typedef std::vector<AbstractStatement*> stmt_vec_t;
65class QoreParseLocationHelper {
67 DLLLOCAL QoreParseLocationHelper(
const char* file,
const char* src =
nullptr,
int offset = 0) {
69 thread_set_class_and_ns(
nullptr,
nullptr, cls, ns);
70 beginParsing(file,
nullptr, src, offset);
73 DLLLOCAL ~QoreParseLocationHelper() {
75 thread_set_class_and_ns(cls, ns);
80 const qore_class_private* cls;
85typedef safe_dslist<LocalVar*> local_var_list_t;
88typedef StatementBlock* q_exp_t;
90class LocalVariableList :
public local_var_list_t {
92 DLLLOCAL LocalVariableList() {
95 DLLLOCAL ~LocalVariableList() {
96 for (local_var_list_t::iterator i = begin(), e = end(); i != e; ++i) {
104#include "qore/intern/ThreadLocalVariableData.h"
105#include "qore/intern/ThreadClosureVariableStack.h"
107hashdecl ThreadLocalProgramData {
110 ThreadLocalVariableData lvstack;
112 ThreadClosureVariableStack cvstack;
114 const AbstractQoreZoneInfo* tz =
nullptr;
121 DLLLOCAL ThreadLocalProgramData() : tz_set(false), inst(false) {
122 printd(5,
"ThreadLocalProgramData::ThreadLocalProgramData() this: %p\n",
this);
125 DLLLOCAL ~ThreadLocalProgramData() {
126 printd(5,
"ThreadLocalProgramData::~ThreadLocalProgramData() this: %p, rs: %d\n",
this, runState);
127 assert(lvstack.empty());
128 assert(cvstack.empty());
132 lvstack.finalize(sdh);
133 cvstack.finalize(sdh);
142 DLLLOCAL
void setTZ(
const AbstractQoreZoneInfo* n_tz) {
147 DLLLOCAL
void clearTZ() {
185 DLLLOCAL
int dbgStep(
const StatementBlock* blockStatement,
const AbstractStatement* statement,
ExceptionSink* xsink);
189 DLLLOCAL
void dbgFunctionEnter(
const StatementBlock* statement,
ExceptionSink* xsink);
193 DLLLOCAL
void dbgFunctionExit(
const StatementBlock* statement,
QoreValue& returnValue,
ExceptionSink* xsink);
197 DLLLOCAL
void dbgException(
const AbstractStatement* statement,
ExceptionSink* xsink);
206 DLLLOCAL
void dbgBreak() {
207 printd(5,
"ThreadLocalProgramData::dbgBreak(), this: %p\n",
this);
213 DLLLOCAL
void dbgPendingAttach() {
214 printd(5,
"ThreadLocalProgramData::dbgPendingAttach(), this: %p\n",
this);
220 DLLLOCAL
void dbgPendingDetach() {
221 printd(5,
"ThreadLocalProgramData::dbgPendingDetach(), this: %p\n",
this);
228 DLLLOCAL
bool dbgIsAttached() {
229 return runState != DBG_RS_DETACH;
232 DLLLOCAL
bool runtimeCheck()
const {
233 return runState != DBG_RS_DETACH || attachFlag || breakFlag;
238 DLLLOCAL ThreadLocalProgramData(
const ThreadLocalProgramData& old) =
delete;
241 DebugRunStateEnum runState = DBG_RS_DETACH;
243 const AbstractStatement* runToStatement =
nullptr;
245 int functionCallLevel = 0;
247 DLLLOCAL
inline void setRunState(DebugRunStateEnum rs,
const AbstractStatement* rts) {
248 assert(rs < DBG_RS_STOPPED);
249 if (rs == DBG_RS_UNTIL_RETURN) {
250 functionCallLevel = 1;
252 printd(5,
"ThreadLocalProgramData::setRunState(), this: %p, rs: %d->%d, rts: %p\n",
this, runState, rs, rts);
254 runToStatement = rts;
257 volatile bool breakFlag =
false;
259 DLLLOCAL
inline void checkBreakFlag() {
260 if (breakFlag && runState != DBG_RS_DETACH) {
262 if (runState != DBG_RS_STOPPED) {
263 runState = DBG_RS_STEP;
265 printd(5,
"ThreadLocalProgramData::checkBreakFlag(), this: %p, rs: %d\n",
this, runState);
271 if (attachFlag && runState != DBG_RS_STOPPED) {
272 if (attachFlag > 0) {
277 }
else if (attachFlag < 0) {
286typedef vector_map_t<ThreadProgramData*, ThreadLocalProgramData*> pgm_data_map_t;
290typedef vector_map_t<std::string, QoreValue> dmap_t;
294typedef vector_map_t<const char*, int64> ppo_t;
297class AbstractQoreZoneInfo;
301 DLLLOCAL
bool operator()(
const QoreProgramLocation* p1,
const QoreProgramLocation* p2)
const {
309hashdecl pgmloc_vec_t :
public std::vector<QoreProgramLocation*> {
310 DLLLOCAL ~pgmloc_vec_t() {
314 DLLLOCAL
void clear() {
315 for (
auto& i : *
this) {
319 std::vector<QoreProgramLocation*>::clear();
323class qore_program_private_base {
324 friend class QoreProgramAccessHelper;
327 LocalVariableList local_var_list;
332 unsigned thread_count = 0;
333 unsigned thread_waiting = 0;
334 unsigned parse_count = 0;
344 typedef std::set<const char*, ltstr> str_set_t;
348 typedef std::set<const QoreProgramLocation*, ltpgm> loc_set_t;
351 typedef std::set<std::string> strset_t;
353 strset_t featureList;
356 strset_t userFeatureList;
359 strset_t parse_modules;
370 * warnSink =
nullptr,
371 * pendingParseSink =
nullptr;
376 TopLevelStatementBlock sb;
379 bool only_first_except : 1,
381 po_allow_restrict : 1,
384 requires_exception : 1,
386 parsing_in_progress : 1,
392 typedef std::set<q_exp_t> q_exp_set_t;
394 q_exp_t new_expression =
nullptr;
398 int exceptions_raised = 0,
401 ParseWarnOptions pwo;
406 std::string exec_class_name, script_dir, script_path, script_name, include_path;
413 mutable unsigned twaiting = 0;
416 pgm_data_map_t pgm_data_map;
419 const AbstractQoreZoneInfo* TZ;
437 : plock(&ma_recursive),
439 only_first_except(false),
441 po_allow_restrict(true),
444 requires_exception(false),
446 parsing_in_progress(false),
449 expression_mode(false),
450 pwo(n_parse_options),
452 printd(QPP_DBG_LVL,
"qore_program_private_base::qore_program_private_base() this: %p pgm: %p po: " QLLD
"\n",
453 this, pgm, n_parse_options);
456 pgm->priv = (qore_program_private*)
this;
459 setParent(p_pgm, n_parse_options);
461 TZ = QTZM.getLocalZoneInfo();
466 Var *var = qore_root_ns_private::runtimeCreateVar(*RootNS, *QoreNS,
"ARGV", listTypeInfo,
true);
468 var->setInitial(ARGV->
copy());
470 var = qore_root_ns_private::runtimeCreateVar(*RootNS, *QoreNS,
"QORE_ARGV", listTypeInfo,
true);
471 if (var && QORE_ARGV)
472 var->setInitial(QORE_ARGV->
copy());
474 var = qore_root_ns_private::runtimeCreateVar(*RootNS, *QoreNS,
"ENV", hashTypeInfo,
true);
476 var->setInitial(ENV->
copy());
481 DLLLOCAL ~qore_program_private_base() {
482 printd(QPP_DBG_LVL,
"qore_program_private_base::~qore_program_private_base() this: %p pgm: %p\n",
this, pgm);
486 DLLLOCAL
const QoreProgramLocation* getLocation(
int sline,
int eline);
487 DLLLOCAL
const QoreProgramLocation* getLocation(
const QoreProgramLocation&,
int sline,
int eline);
492 DLLLOCAL
int64 checkDeserializeParseOptions(
int64 po) {
496 return pwo.parse_options & ~po & ~PO_FREE_STYLE_OPTIONS;
499 DLLLOCAL
void replaceParseOptionsIntern(
int64 po) {
500 pwo.parse_options = po;
503 DLLLOCAL
bool checkSetParseOptions(
int64 po) {
509 DLLLOCAL
void setParseOptionsIntern(
int64 po) {
510 pwo.parse_options |= po;
513 DLLLOCAL
void addParseModule(
const char* mod) {
514 parse_modules.insert(mod);
518 typedef vector_map_t<const char*, AbstractQoreProgramExternalData*> extmap_t;
525 DLLLOCAL
void newProgram();
527 DLLLOCAL
void setDefines();
530class PreParseHelper {
532 qore_program_private_base *p;
536 DLLLOCAL PreParseHelper(qore_program_private_base *n_p) : p(n_p), swapped(false) {
538 if (!p->pendingParseSink)
540 p->parseSink = p->pendingParseSink;
545 DLLLOCAL ~PreParseHelper() {
547 p->parseSink =
nullptr;
552class qore_debug_program_private;
554class AutoQoreCounterDec {
556 DLLLOCAL AutoQoreCounterDec(
QoreCounter* n_cnt,
bool incNow =
true): cnt(n_cnt), incFlag(false) {
562 DLLLOCAL ~AutoQoreCounterDec() {
568 DLLLOCAL
void inc() {
577 DLLLOCAL AutoQoreCounterDec() {}
582class qore_program_private :
public qore_program_private_base {
584 typedef std::map<const char*, int, ltstr> section_offset_map_t;
586 typedef std::map<int, AbstractStatement*> sline_statement_map_t;
588 hashdecl section_sline_statement_map {
589 section_offset_map_t sectionMap;
590 sline_statement_map_t statementMap;
593 typedef section_sline_statement_map section_sline_statement_map_t;
595 typedef vector_map_t<const char*, section_sline_statement_map_t*> name_section_sline_statement_map_t;
600 DLLLOCAL ~qore_program_private();
602 DLLLOCAL
void registerProgram();
604 DLLLOCAL
void depRef() {
605 printd(QPP_DBG_LVL,
"qore_program_private::depRef() this: %p pgm: %p %d->%d\n",
this, pgm,
610 DLLLOCAL
void depDeref() {
611 printd(QPP_DBG_LVL,
"qore_program_private::depDeref() this: %p pgm: %p %d->%d\n",
this, pgm,
629 for (
auto& i : pgm_data_map) {
630 i.second->finalize(sdh);
636 for (
auto& i : pgm_data_map) {
637 i.second->del(xsink);
638 i.first->delProgram(pgm);
642 DLLLOCAL
void waitForTerminationAndClear(
ExceptionSink* xsink);
654 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed has already been deleted and therefore no "
655 "new threads can be started in it");
664 DLLLOCAL
void cancelPreregistration() {
668 assert(thread_count > 0);
669 if (!--thread_count && thread_waiting)
674 DLLLOCAL
void registerNewThread(
int tid) {
678 assert(thread_count);
700 if (ptid && ptid != tid) {
701 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed has already been deleted and therefore "
702 "cannot be accessed at runtime");
705 if (parsing_in_progress) {
706 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed is currently undergoing parsing and cannot "
707 "be accessed at runtime");
716 DLLLOCAL
void incThreadCount() {
722 if (ptid && ptid != tid) {
724 "therefore cannot be accessed at runtime");
726 if (parsing_in_progress) {
727 throw QoreStandardException(
"PROGRAM-ERROR",
"the Program accessed is currently undergoing parsing and "
728 "cannot be accessed at runtime");
735 DLLLOCAL
void decThreadCount(
int tid) {
739 ptid_map_t::iterator i = tidmap.find(tid);
740 assert(i != tidmap.end());
744 assert(thread_count > 0);
745 if (!--thread_count && thread_waiting)
754 for (
auto& i : tidmap) {
755 l.
push(i.first,
nullptr);
764 while (parse_tid != -1 && parse_tid != tid && !ptid) {
772 xsink->
raiseException(
"PROGRAM-ERROR",
"the Program accessed has already been deleted and "
773 "therefore cannot be accessed");
785 DLLLOCAL
void unlockParsing() {
789 assert(parse_count > 0);
790 if (!(--parse_count)) {
792 if (thread_waiting) {
798 DLLLOCAL
bool parsingLocked()
const {
803 DLLLOCAL
void waitForAllThreadsToTerminateIntern() {
806 ptid_map_t::iterator i = tidmap.find(tid);
807 unsigned adj = (i != tidmap.end() ? 1 : 0);
809 while ((thread_count - adj) || parse_count) {
816 DLLLOCAL
void waitForAllThreadsToTerminate() {
819 waitForAllThreadsToTerminateIntern();
822 DLLLOCAL
const char* parseGetScriptPath()
const {
823 return script_path.empty() ? nullptr : script_path.c_str();
826 DLLLOCAL
const char* parseGetScriptDir()
const {
827 return script_dir.empty() ? nullptr : script_dir.c_str();
830 DLLLOCAL
const char* parseGetScriptName()
const {
831 return script_name.empty() ? nullptr : script_name.c_str();
837 return script_path.empty() ? nullptr :
new QoreStringNode(script_path);
843 return script_dir.empty() ? nullptr :
new QoreStringNode(script_dir);
849 return script_name.empty() ? nullptr :
new QoreStringNode(script_name);
852 DLLLOCAL
void setScriptPathExtern(
const char* path) {
858 DLLLOCAL
void setScriptPath(
const char* path) {
868 script_dir =
"." QORE_DIR_SEP_STR;
869 script_path = script_dir + script_name;
873 script_dir.assign(path, p - path);
887 for (
auto& i : featureList) {
896 DLLLOCAL
int internParsePending(
ExceptionSink* xsink,
const char* code,
const char* label,
897 const char* orig_src =
nullptr,
int offset = 0,
bool standard_parse =
true) {
901 assert(code && code[0]);
905 const char* sname = label;
906 const char* src = orig_src;
908 addFile(src, sname, offset);
916 QoreParseLocationHelper qplh(sname, src, offset);
919 beginParsing(sname,
nullptr, src, offset);
921 if (!parsing_in_progress) {
922 parsing_in_progress =
true;
931 yy_scan_string(code, lexer);
932 yyset_lineno(1, lexer);
936 printd(5,
"qore_program_private::internParsePending() returned from yyparse()\n");
940 if (standard_parse) {
941 printd(5,
"qore_program_private::internParsePending() parse exception: calling parseRollback()\n");
942 internParseRollback(xsink);
943 requires_exception =
false;
947 printd(5,
"qore_program_private::internParsePending() about to call yylex_destroy()\n");
948 yylex_destroy(lexer);
949 printd(5,
"qore_program_private::internParsePending() returned from yylex_destroy()\n");
958 if (pendingParseSink) {
960 pendingParseSink =
nullptr;
966 xsink->
raiseException(
"PARSE-ERROR",
"parsing can only happen once for each Program container");
973 const char* orig_src =
nullptr,
int offset = 0) {
976 ProgramRuntimeParseContextHelper pch(xsink, pgm);
982 if (checkParse(xsink)) {
986 startParsing(xsink, wS, wm);
988 int rc = internParsePending(xsink, code, label, orig_src, offset);
997 DLLLOCAL
int internParseCommit(
bool standard_parse =
true);
1000 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1006 if (checkParse(xsink)) {
1010 startParsing(xsink, wS, wm);
1013 int rc = internParseCommit();
1016 parseSink =
nullptr;
1024 ProgramRuntimeParseContextHelper pch(xsink, pgm);
1030 internParseRollback(xsink);
1036 printd(5,
"QoreProgram::parse(fp: %p, name: %s, xsink: %p, wS: %p, wm: %d)\n", fp, name, xsink, wS, wm);
1042 printd(5,
"QoreProgram::parse(fp: %p, name: %s) EOF\n", fp, name);
1051 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1056 if (checkParse(xsink)) {
1060 startParsing(xsink, wS, wm);
1064 const char* sname = name;
1070 QoreParseLocationHelper qplh(sname);
1073 beginParsing(sname);
1075 if (!parsing_in_progress) {
1076 parsing_in_progress =
true;
1081 yyset_in(fp, lexer);
1086 internParseCommit();
1089 parseSink =
nullptr;
1095 yylex_destroy(lexer);
1096 if (only_first_except && exceptions_raised > 1)
1097 fprintf(stderr,
"\n%d exception(s) skipped\n\n", exceptions_raised);
1101 int wm,
const QoreString* source =
nullptr,
int offset = 0) {
1117 if (source && !source->empty() && !src.
set(source,
QCS_DEFAULT, xsink))
1120 parse(tstr->c_str(), tlstr->c_str(), xsink, wS, wm, source ? src->
c_str() :
nullptr, offset);
1124 const char* orig_src =
nullptr,
int offset = 0) {
1127 assert(code && code[0]);
1130 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1135 if (checkParse(xsink)) {
1139 startParsing(xsink, wS, wm);
1142 if (!internParsePending(xsink, code, label, orig_src, offset))
1143 internParseCommit();
1146 parseSink =
nullptr;
1158 xsink->
raiseException(
"STATEMENT-ERROR",
"the statement cannot be empty");
1175 if (source && !source->empty() && !src.
set(source,
QCS_DEFAULT, xsink)) {
1179 return parseStatement(tstr->c_str(), tlstr->c_str(), xsink, wS, wm, source ? src->
c_str() :
nullptr, offset);
1183 int wm,
const char* orig_src =
nullptr,
int offset = 0) {
1186 assert(code && code[0]);
1189 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1194 startParsing(xsink, wS, wm);
1197 if (!internParsePending(xsink, code, label, orig_src, offset,
false)) {
1198 internParseCommit(
false);
1200 parsing_in_progress =
false;
1204 parseSink =
nullptr;
1207 return *xsink ? -1 : 0;
1215 xsink->
raiseException(
"EXPRESSION-ERROR",
"the expression cannot be empty");
1230 if (source && !source->empty() && !src.
set(source,
QCS_DEFAULT, xsink))
1233 return parseExpression(tstr->c_str(), tlstr->c_str(), xsink, wS, wm, source ? src->
c_str() :
nullptr, offset);
1237 int wm,
const char* orig_src =
nullptr,
int offset = 0) {
1240 assert(code && code[0]);
1243 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1248 assert(!expression_mode);
1249 assert(!new_expression);
1250 expression_mode =
true;
1252 QoreStringMaker exp_code(
"return (%s);", code);
1254 startParsing(xsink, wS, wm);
1257 if (!internParsePending(xsink, exp_code.c_str(), label, orig_src, offset,
false)) {
1258 internParseCommit(
false);
1260 parsing_in_progress =
false;
1264 parseSink =
nullptr;
1268 expression_mode =
false;
1269 q_exp_t rv = new_expression;
1270 if (new_expression) {
1272 exp_set.erase(new_expression);
1273 delete new_expression;
1276 new_expression =
nullptr;
1282 QORE_TRACE(
"QoreProgram::parseFile()");
1284 printd(5,
"QoreProgram::parseFile(%s)\n", filename);
1287 if (!(fp = fopen(filename,
"r"))) {
1288 if ((only_first_except && !exceptions_raised) || !only_first_except)
1289 xsink->
raiseErrnoException(
"PARSE-EXCEPTION", errno,
"cannot open qore script '%s'", filename);
1290 exceptions_raised++;
1293 ON_BLOCK_EXIT(fclose, fp);
1295 setScriptPath(filename);
1297 ProgramRuntimeParseCommitContextHelper pch(xsink, pgm);
1301 parse(fp, filename, xsink, wS, wm);
1305 assert(!str->
empty());
1319 if (source && !source->empty() && !src.
set(source,
QCS_DEFAULT, xsink))
1322 parsePending(tstr->c_str(), tlstr->c_str(), xsink, wS, wm, source ? src->
c_str() :
nullptr, offset);
1326 DLLLOCAL
void importFunction(
ExceptionSink* xsink, QoreFunction *u,
const qore_ns_private& oldns,
const char* new_name =
nullptr,
bool inject =
false);
1334 thread_local_storage->
set(h);
1342 printd(5,
"QoreProgram::clearThreadData() this: %p h: %p (size: %d)\n",
this, h, h ? h->
size() : 0);
1352 thread_local_storage->
set(
nullptr);
1356 DLLLOCAL
void finalizeThreadData(ThreadProgramData* td,
SafeDerefHelper& sdh) {
1360 thread_local_storage->
set(
nullptr);
1368 pgm_data_map_t::iterator i = pgm_data_map.find(td);
1369 if (i != pgm_data_map.end()) {
1370 i->second->finalize(sdh);
1375 DLLLOCAL
int endThread(ThreadProgramData* td,
ExceptionSink* xsink) {
1376 ThreadLocalProgramData* tlpd =
nullptr;
1385 pgm_data_map_t::iterator i = pgm_data_map.find(td);
1386 if (i == pgm_data_map.end()) {
1390 pgm_data_map.erase(i);
1397 DLLLOCAL
void doTopLevelInstantiation(ThreadLocalProgramData& tlpd) {
1399 const LVList* lvl = sb.getLVList();
1401 for (
unsigned i = 0; i < lvl->size(); ++i) {
1402 lvl->lv[i]->instantiate(pwo.parse_options);
1412 DLLLOCAL
bool setThreadVarData(ThreadProgramData* td, ThreadLocalProgramData*& new_tlpd,
bool run) {
1426 pgm_data_map_t::iterator i = pgm_data_map.find(td);
1427 if (i == pgm_data_map.end()) {
1430 ThreadLocalProgramData* tlpd =
new ThreadLocalProgramData;
1432 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");
1436 pgm_data_map.insert(pgm_data_map_t::value_type(td, tlpd));
1441 printd(5,
"qore_program_private::setThreadVarData() (first) this: %p pgm: %p td: %p\n",
this, pgm, td);
1442 doTopLevelInstantiation(*tlpd);
1448 ThreadLocalProgramData* tlpd = pgm_data_map[td];
1453 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");
1455 if (run && !tlpd->inst) {
1456 doTopLevelInstantiation(*tlpd);
1462 DLLLOCAL
const AbstractQoreZoneInfo* currentTZ(ThreadProgramData* tpd = get_thread_program_data())
const {
1464 pgm_data_map_t::const_iterator i = pgm_data_map.find(tpd);
1465 if (i != pgm_data_map.end() && i->second->tz_set)
1466 return i->second->tz;
1470 DLLLOCAL
void setTZ(
const AbstractQoreZoneInfo* n_TZ) {
1474 DLLLOCAL
void exportFunction(
ExceptionSink* xsink, qore_program_private* p,
const char* name,
const char* new_name =
nullptr,
bool inject =
false) {
1476 xsink->
raiseException(
"FUNCTION-IMPORT-ERROR",
"cannot import a function from the same Program object");
1481 xsink->
raiseException(
"FUNCTION-IMPORT-ERROR",
"cannot import function \"%s\" in a Program object without PO_ALLOW_INJECTION set", name);
1485 const QoreFunction* u;
1486 const qore_ns_private* ns =
nullptr;
1489 ProgramRuntimeParseAccessHelper rah(xsink, pgm);
1492 u = qore_root_ns_private::runtimeFindFunction(*RootNS, name, ns);
1496 xsink->
raiseException(
"PROGRAM-IMPORTFUNCTION-NO-FUNCTION",
"function '%s' does not exist in the current program scope", name);
1499 p->importFunction(xsink,
const_cast<QoreFunction*
>(u), *ns, new_name, inject);
1503 DLLLOCAL
bool parseExceptionRaised()
const {
1508 DLLLOCAL
void disableParseOptionsIntern(
int64 po) {
1509 pwo.parse_options &= ~po;
1514 if (checkSetParseOptions(po)) {
1515 xsink->
raiseException(
"OPTIONS-LOCKED",
"parse options have been locked on this program object");
1519 setParseOptionsIntern(po);
1527 if (((po &
PO_FREE_OPTIONS) != po) && po_locked && !po_allow_restrict) {
1528 xsink->
raiseException(
"OPTIONS-LOCKED",
"parse options have been locked on this program object");
1532 disableParseOptionsIntern(po);
1539 xsink->
raiseException(
"OPTION-ERROR",
"the calling Program does not have the PO_NO_CHILD_PO_RESTRICTIONS option set, and therefore cannot call Program::replaceParseOptions()");
1544 replaceParseOptionsIntern(po);
1548 DLLLOCAL
int parseSetParseOptions(
const QoreProgramLocation* loc,
int64 po) {
1552 parse_error(*loc,
"parse options have been locked on this program object");
1556 setParseOptionsIntern(po);
1560 DLLLOCAL
int parseDisableParseOptions(
const QoreProgramLocation* loc,
int64 po) {
1563 if (((po &
PO_FREE_OPTIONS) != po) && po_locked && !po_allow_restrict) {
1564 parse_error(*loc,
"parse options have been locked on this program object");
1568 disableParseOptionsIntern(po);
1572 DLLLOCAL
void parseSetTimeZone(
const char* zone) {
1576 mergeParseException(xsink);
1580 const AbstractQoreZoneInfo *tz = (*zone ==
'-' || *zone ==
'+') ? QTZM.findCreateOffsetZone(zone, &xsink) : QTZM.findLoadRegion(zone, &xsink);
1583 mergeParseException(xsink);
1587 assert(tz || ((*zone ==
'-' || *zone ==
'+')));
1592 DLLLOCAL
void makeParseException(
const QoreProgramLocation& loc,
const char* err,
QoreStringNode* desc) {
1593 QORE_TRACE(
"QoreProgram::makeParseException()");
1596 if (!requires_exception) {
1597 if ((only_first_except && !exceptions_raised) || !only_first_except) {
1598 QoreException *ne =
new ParseException(loc, err, d.release());
1601 exceptions_raised++;
1605 DLLLOCAL
void parseException(
const QoreProgramLocation& loc,
const char* fmt, ...) {
1609 if (requires_exception)
1615 va_start(args, fmt);
1616 int rc = desc->
vsprintf(fmt, args);
1621 makeParseException(loc,
"PARSE-EXCEPTION", desc);
1627 dmap_t::iterator i = dmap.find(name);
1628 if (i != dmap.end()) {
1629 i->second.discard(xsink);
1639 DLLLOCAL
const QoreValue getDefine(
const char* name,
bool& is_defined) {
1640 dmap_t::iterator i = dmap.find(name);
1641 if (i != dmap.end()) {
1649 DLLLOCAL
QoreValue runTimeGetDefine(
const char* name,
bool& is_defined) {
1651 return getDefine(name, is_defined).refSelf();
1658 DLLLOCAL
bool unDefine(
const char* name,
ExceptionSink* xsink) {
1659 dmap_t::iterator i = dmap.find(name);
1660 if (i != dmap.end()) {
1661 i->second.discard(xsink);
1668 DLLLOCAL
bool parseUnDefine(
const char* name) {
1669 PreParseHelper pph(
this);
1670 return unDefine(name, parseSink);
1673 DLLLOCAL
bool runTimeUnDefine(
const char* name,
ExceptionSink* xsink) {
1675 return unDefine(name, xsink);
1679 DLLLOCAL
bool isDefined(
const char* name) {
1680 dmap_t::iterator i = dmap.find(name);
1681 return i == dmap.end() ? false :
true;
1684 DLLLOCAL
bool runTimeIsDefined(
const char* name) {
1686 return isDefined(name);
1689 DLLLOCAL
int checkDefine(
const QoreProgramLocation* loc,
const char* str,
ExceptionSink* xsink) {
1690 const char* p = str;
1692 xsink->
raiseException(*loc,
"PARSE-EXCEPTION", 0,
"illegal define variable '%s'; does not begin with an alphabetic character", p);
1697 if (!isalnum(*p) && *p !=
'_') {
1699 xsink->
raiseException(*loc,
"PARSE-EXCEPTION", 0,
"illegal character '%c' in define variable '%s'", *p, str);
1707 DLLLOCAL
void parseDefine(
const QoreProgramLocation* loc,
const char* str,
QoreValue val) {
1708 PreParseHelper pph(
this);
1710 if (checkDefine(loc, str, parseSink))
1713 setDefine(str, val, parseSink);
1717 const QoreProgramLocation* loc = get_runtime_location();
1719 if (checkDefine(loc, str, xsink))
1723 setDefine(str, val, xsink);
1728 ProgramRuntimeParseAccessHelper pah(xsink, pgm);
1731 return qore_root_ns_private::runtimeGetCallReference(*RootNS, name, xsink);
1734 DLLLOCAL
void pushParseOptions(
const char* pf) {
1736 ppo_t::iterator i = ppo.lower_bound(pf);
1737 if (i != ppo.end() && !strcmp(pf, i->first))
1739 ppo.insert(i, ppo_t::value_type(pf, pwo.parse_options));
1743 DLLLOCAL
void restoreParseOptions(
const char* pf) {
1744 ppo_t::iterator i = ppo.find(pf);
1745 if (i != ppo.end()) {
1747 pwo.parse_options = i->second;
1752 DLLLOCAL
void addParseException(
ExceptionSink& xsink,
const QoreProgramLocation* loc) {
1753 if (requires_exception) {
1760 xsink.overrideLocation(*loc);
1776 if ((pos & p_tmp) != pos) {
1777 rv = ((pos & p_tmp) ^ pos);
1781 int64 neg = (n_dom & ~PO_POSITIVE_OPTIONS);
1782 if (neg && (neg & pwo.parse_options)) {
1783 rv |= (neg & pwo.parse_options);
1791 DLLLOCAL
void exportGlobalVariable(
const char* name,
bool readonly, qore_program_private& tpgm,
ExceptionSink* xsink);
1798 DLLLOCAL
void setThreadTZ(ThreadProgramData* tpd,
const AbstractQoreZoneInfo* tz) {
1800 pgm_data_map_t::iterator i = pgm_data_map.find(tpd);
1801 assert(i != pgm_data_map.end());
1802 i->second->setTZ(tz);
1805 DLLLOCAL
const AbstractQoreZoneInfo* getThreadTZ(ThreadProgramData* tpd,
bool& set)
const {
1807 pgm_data_map_t::const_iterator i = pgm_data_map.find(tpd);
1808 assert(i != pgm_data_map.end());
1809 set = i->second->tz_set;
1810 return i->second->tz;
1813 DLLLOCAL
void clearThreadTZ(ThreadProgramData* tpd) {
1815 pgm_data_map_t::iterator i = pgm_data_map.find(tpd);
1816 assert(i != pgm_data_map.end());
1817 i->second->clearTZ();
1820 DLLLOCAL
void addStatement(AbstractStatement* s);
1824 return parseExpression(source, label, xsink);
1828 ProgramThreadCountContextHelper pch(xsink, pgm,
true);
1832 if (exp_set.find(exp) == exp_set.end()) {
1833 xsink->
raiseException(
"INVALID-EXPRESSION",
"expression not registered to this Program object");
1836 ThreadFrameBoundaryHelper tfbh(
true);
1842 return rv.release();
1845 DLLLOCAL
void deleteExpression(q_exp_t exp) {
1847 q_exp_set_t::iterator i = exp_set.find(exp);
1848 if (i != exp_set.end()) {
1854 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);
1856 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);
1858 DLLLOCAL
const char* addString(
const char* str) {
1859 str_set_t::iterator i = str_set.lower_bound(str);
1860 if (i == str_set.end() || strcmp(*i, str)) {
1861 str_vec.push_back(strdup(str));
1862 i = str_set.insert(i, str_vec.back());
1867 DLLLOCAL
void addFile(
const char*& file) {
1868 file = addString(file);
1869 printd(5,
"qore_program_private::addFile('%s')\n", file);
1870 addStatementToIndexIntern(&statementByFileIndex, file,
nullptr, -1,
nullptr, -1);
1873 DLLLOCAL
void addFile(
const char*& file,
const char*& source,
int offset) {
1874 file = addString(file);
1876 source = addString(source);
1878 printd(5,
"qore_program_private::addFile('%s', '%s', %d)\n", file, source ? source :
"(null)", offset);
1879 addStatementToIndexIntern(&statementByFileIndex, file,
nullptr, -1, source, offset);
1881 addStatementToIndexIntern(&statementByLabelIndex, source,
nullptr, -1, file, offset);
1885 DLLLOCAL
int addFeature(
const char* f) {
1887 strset_t::iterator i = featureList.lower_bound(f);
1888 if (i != featureList.end() && (*i == f)) {
1892 featureList.insert(i, f);
1896 DLLLOCAL
void removeFeature(
const char* f) {
1897 strset_t::iterator i = featureList.find(f);
1898 assert(i != featureList.end());
1899 featureList.erase(i);
1902 DLLLOCAL
int addUserFeature(
const char* f) {
1904 strset_t::iterator i = userFeatureList.lower_bound(f);
1905 if (i != userFeatureList.end() && (*i == f)) {
1909 userFeatureList.insert(i, f);
1913 DLLLOCAL
bool hasUserFeature(
const std::string feature)
const {
1914 return userFeatureList.find(feature) != userFeatureList.end();
1917 DLLLOCAL
void removeUserFeature(
const char* f) {
1918 strset_t::iterator i = userFeatureList.find(f);
1919 assert(i != userFeatureList.end());
1920 userFeatureList.erase(i);
1923 DLLLOCAL
bool hasFeature(
const char* f)
const {
1924 return (featureList.find(f) != featureList.end())
1925 || (userFeatureList.find(f) != userFeatureList.end());
1928 DLLLOCAL
void runtimeImportSystemClassesIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1929 DLLLOCAL
void runtimeImportSystemConstantsIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1930 DLLLOCAL
void runtimeImportSystemFunctionsIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1931 DLLLOCAL
void runtimeImportSystemHashDeclsIntern(
const qore_program_private& spgm,
ExceptionSink* xsink);
1933 DLLLOCAL
void runtimeImportSystemClasses(
ExceptionSink* xsink);
1934 DLLLOCAL
void runtimeImportSystemConstants(
ExceptionSink* xsink);
1935 DLLLOCAL
void runtimeImportSystemFunctions(
ExceptionSink* xsink);
1936 DLLLOCAL
void runtimeImportSystemHashDecls(
ExceptionSink* xsink);
1945 assert(extmap.find(owner) == extmap.end());
1946 extmap.insert(extmap_t::value_type(owner, pud));
1951 extmap_t::const_iterator i = extmap.find(owner);
1952 return i == extmap.end() ? nullptr : i->second;
1957 extmap_t::iterator i = extmap.find(owner);
1958 if (i == extmap.end()) {
1967 return qore_root_ns_private::getGlobalVars(*RootNS);
1970 DLLLOCAL LocalVar* createLocalVar(
const char* name,
const QoreTypeInfo* typeInfo);
1972 DLLLOCAL
const AbstractQoreFunctionVariant* runtimeFindCall(
const char* name,
const QoreListNode* params,
ExceptionSink* xsink);
1977 return pgm.priv->runtimeFindClass(class_name, xsink);
1981 pgm.priv->doThreadInit(xsink);
1986 if (!pgm.priv->exec_class) {
1987 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>))");
1990 pgm.priv->exec_class_rv.discard(xsink);
1991 pgm.priv->exec_class_rv = rv.release();
1997 return pgm.priv->preregisterNewThread(xsink);
2001 DLLLOCAL
static void cancelPreregistration(
QoreProgram& pgm) {
2002 pgm.priv->cancelPreregistration();
2006 DLLLOCAL
static void registerNewThread(
QoreProgram& pgm,
int tid) {
2007 pgm.priv->registerNewThread(tid);
2011 pgm.priv->runtimeImportSystemClasses(xsink);
2015 pgm.priv->runtimeImportSystemHashDecls(xsink);
2019 pgm.priv->runtimeImportSystemConstants(xsink);
2023 pgm.priv->runtimeImportSystemFunctions(xsink);
2027 pgm.priv->runtimeImportSystemApi(xsink);
2030 DLLLOCAL
static qore_program_private* get(
QoreProgram& pgm) {
2035 pgm.priv->clearThreadData(xsink);
2038 DLLLOCAL
static void addStatement(
QoreProgram& pgm, AbstractStatement* s) {
2039 pgm.priv->addStatement(s);
2042 DLLLOCAL
static const AbstractQoreZoneInfo* currentTZIntern(
QoreProgram& pgm) {
2043 return pgm.priv->TZ;
2047 return pgm.priv->lockParsing(xsink);
2050 DLLLOCAL
static void unlockParsing(
QoreProgram& pgm) {
2051 pgm.priv->unlockParsing();
2055 return pgm.priv->incThreadCount(xsink);
2058 DLLLOCAL
static void decThreadCount(
QoreProgram& pgm,
int tid) {
2059 pgm.priv->decThreadCount(tid);
2063 DLLLOCAL
static void addSignal(
QoreProgram& pgm,
int sig) {
2064 assert(pgm.priv->sigset.find(sig) == pgm.priv->sigset.end());
2065 pgm.priv->sigset.insert(sig);
2069 DLLLOCAL
static void delSignal(
QoreProgram& pgm,
int sig) {
2070 assert(pgm.priv->sigset.find(sig) != pgm.priv->sigset.end());
2071 pgm.priv->sigset.erase(sig);
2075 pgm.priv->qore_program_private_base::startThread(xsink);
2080 return pgm.priv->setThreadInit(n_thr_init, xsink);
2085 return pgm->priv->runtimeGetCallReference(name, xsink);
2088 DLLLOCAL
static const ParseWarnOptions& getParseWarnOptions(
const QoreProgram* pgm) {
2089 return pgm->priv->pwo;
2092 DLLLOCAL
static bool setSaveParseWarnOptions(
const QoreProgram* pgm,
const ParseWarnOptions &new_opts,
2093 ParseWarnOptions &old_opts) {
2094 if (new_opts == pgm->priv->pwo)
2096 old_opts = pgm->priv->pwo;
2097 pgm->priv->pwo = new_opts;
2101 DLLLOCAL
static void setParseWarnOptions(
const QoreProgram* pgm,
const ParseWarnOptions &new_opts) {
2102 pgm->priv->pwo = new_opts;
2105 DLLLOCAL
static bool setThreadVarData(
QoreProgram* pgm, ThreadProgramData* td, ThreadLocalProgramData* &tlpd,
2107 return pgm->priv->setThreadVarData(td, tlpd, run);
2111 pgm->priv->makeParseException(loc,
"PARSE-EXCEPTION", desc);
2114 DLLLOCAL
static void makeParseException(
QoreProgram* pgm,
const QoreProgramLocation &loc,
const char* err,
2116 pgm->priv->makeParseException(loc, err, desc);
2121 return pgm->priv->getDefine(name, is_defined);
2124 DLLLOCAL
static const QoreValue parseGetDefine(
QoreProgram* pgm,
const char* name,
bool& is_defined) {
2125 return pgm->priv->getDefine(name, is_defined);
2130 return pgm->priv->runTimeGetDefine(name, is_defined);
2133 DLLLOCAL
static QoreValue runTimeGetDefine(
QoreProgram* pgm,
const char* name,
bool& is_defined) {
2134 return pgm->priv->runTimeGetDefine(name, is_defined);
2138 return pgm->priv->runTimeGetAllDefines();
2141 DLLLOCAL
static bool parseUnDefine(
QoreProgram* pgm,
const char* name) {
2142 return pgm->priv->parseUnDefine(name);
2146 return pgm->priv->runTimeUnDefine(name, xsink);
2149 DLLLOCAL
static bool parseIsDefined(
QoreProgram* pgm,
const char* name) {
2150 return pgm->priv->isDefined(name);
2153 DLLLOCAL
static bool runTimeIsDefined(
QoreProgram* pgm,
const char* name) {
2154 return pgm->priv->runTimeIsDefined(name);
2157 DLLLOCAL
static void parseDefine(
QoreProgram* pgm,
const QoreProgramLocation* loc,
const char* str,
2159 pgm->priv->parseDefine(loc, str, val);
2163 pgm->priv->runTimeDefine(str, val, xsink);
2167 const QoreProgramLocation* loc =
nullptr) {
2169 pgm->priv->addParseException(*xsink, loc);
2174 const QoreProgramLocation* loc =
nullptr) {
2175 pgm->priv->addParseException(xsink, loc);
2179 const char* name,
const char* new_name =
nullptr,
bool inject =
false) {
2180 srcpgm->priv->exportFunction(xsink, trgpgm->priv, name, new_name, inject);
2184 return pgm->priv->parseAddDomain(n_dom);
2188 return pgm.priv->dom;
2192 pgm.priv->dom |= n_dom;
2196 int64 rv = pgm.priv->pwo.parse_options;
2197 pgm.priv->pwo.parse_options = po;
2201 DLLLOCAL
static void makeParseWarning(
QoreProgram* pgm,
const QoreProgramLocation &loc,
int code,
2202 const char* warn,
const char* fmt, ...) {
2206 if (!pgm->priv->warnSink || !(code & pgm->priv->pwo.warn_mask)) {
2213 va_start(args, fmt);
2214 int rc = desc->
vsprintf(fmt, args);
2219 QoreException *ne =
new ParseException(loc, warn, desc);
2220 pgm->priv->warnSink->raiseException(ne);
2223 DLLLOCAL
static void makeParseWarning(
QoreProgram* pgm,
const QoreProgramLocation& loc,
int code,
2228 if (!pgm->priv->warnSink || !(code & pgm->priv->pwo.warn_mask)) {
2233 QoreException *ne =
new ParseException(loc, warn, desc);
2234 pgm->priv->warnSink->raiseException(ne);
2237 DLLLOCAL
static void exportGlobalVariable(
QoreProgram* pgm,
const char* name,
bool readonly,
QoreProgram* tpgm,
2239 pgm->priv->exportGlobalVariable(name, readonly, *(tpgm->priv), xsink);
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()) {
2548 qore_program_to_object_map_t::iterator i = qore_program_to_object_map.find(pgm);
2549 assert(i != qore_program_to_object_map.end());
2551 printd(5,
"qore_program_private::getQoreObject() pgm: %p, pgmid: %d, second: %p\n", i->first, i->first->getProgramId(), i->second);
2555 printd(5,
"qore_program_private::getQoreObject() pgm: %p, pgmid: %d, new second: %p\n", pgm, pgm->
getProgramId(), i->second);
2565 qore_program_to_object_map_t::iterator i = qore_program_to_object_map.begin();
2566 while (i != qore_program_to_object_map.end()) {
2568 printd(5,
"qore_program_private::getAllQoreObjects() pgm: %p, pgmid: %d, second: %p\n", i->first, i->first->getProgramId(), i->second);
2572 printd(5,
"qore_program_private::getAllQoreObjects() pgm: %p, pgmid: %d, new second: %p\n", i->first, i->first->getProgramId(), i->second);
2575 (*l)->push(i->second,
nullptr);
2584 const AbstractQoreZoneInfo* n_TZ = QTZM.getLocalZoneInfo()) {
2592 if (!pendingParseSink)
2598 qore_debug_program_private* dpgm =
nullptr;
2600 QoreBreakpointList_t breakpointList;
2603 name_section_sline_statement_map_t statementByFileIndex;
2604 name_section_sline_statement_map_t statementByLabelIndex;
2607 typedef std::vector<AbstractStatement*> StatementVector_t;
2608 StatementVector_t statementIds;
2611 typedef std::map<AbstractStatement*, unsigned long> ReverseStatementIdMap_t;
2612 ReverseStatementIdMap_t reverseStatementIds;
2620 DLLLOCAL qore_debug_program_private* getDebugProgram(AutoQoreCounterDec& ad) {
2623 qore_debug_program_private* ret = dpgm;
2632 DLLLOCAL
bool isBreakpointRegistered(
const QoreBreakpoint* bkpt)
const {
2633 return std::find(breakpointList.begin(), breakpointList.end(), bkpt) != breakpointList.end();
2637 typedef std::map<QoreProgram*, QoreObject*> qore_program_to_object_map_t;
2638 static qore_program_to_object_map_t qore_program_to_object_map;
2640 static volatile unsigned programIdCounter;
2644class ParseWarnHelper :
public ParseWarnOptions {
2648 DLLLOCAL ParseWarnHelper(
const ParseWarnOptions &new_opts) {
2650 restore = pgm ? qore_program_private::setSaveParseWarnOptions(pgm, new_opts, *
this) : false;
2652 DLLLOCAL ~ParseWarnHelper() {
2654 qore_program_private::setParseWarnOptions(
getProgram(), *
this);
2658typedef std::map<QoreProgram*, qore_program_private*> qore_program_map_t;
2661class qore_debug_program_private {
2663 DLLLOCAL qore_debug_program_private(
QoreDebugProgram* n_dpgm) : dpgm(n_dpgm) {}
2665 DLLLOCAL ~qore_debug_program_private() {
2666 assert(qore_program_map.empty());
2670 if (!pgm->priv->checkAllowDebugging(xsink))
2673 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2674 printd(5,
"qore_debug_program_private::addProgram(), this: %p, pgm: %p, i: %p, end: %p\n",
this, pgm, i,
2675 qore_program_map.end());
2676 if (i != qore_program_map.end())
2678 qore_program_map.insert(qore_program_map_t::value_type(pgm, pgm->priv));
2680 pgm->priv->attachDebug(
this);
2685 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2686 printd(5,
"qore_debug_program_private::removeProgram(), this: %p, pgm: %p, i: %p, end: %p\n",
this, pgm, i,
2687 qore_program_map.end());
2688 if (i == qore_program_map.end())
2690 pgm->priv->detachDebug(
this);
2691 qore_program_map.erase(i);
2696 DLLLOCAL
void removeAllPrograms() {
2698 printd(5,
"qore_debug_program_private::removeAllPrograms(), this: %p\n",
this);
2699 qore_program_map_t::iterator i;
2700 while ((i = qore_program_map.begin()) != qore_program_map.end()) {
2701 qore_program_private* qpp = i->second;
2703 qore_program_map.erase(i);
2704 qpp->detachDebug(
this);
2711 printd(5,
"qore_debug_program_private::getAllProgramObjects(), this: %p\n",
this);
2713 qore_program_map_t::iterator i = qore_program_map.begin();
2714 while (i != qore_program_map.end()) {
2717 (*l)->push(o,
nullptr);
2724 DLLLOCAL
void onAttach(
QoreProgram* pgm, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
2726 AutoQoreCounterDec ad(&debug_program_counter);
2727 dpgm->onAttach(pgm, rs, rts, xsink);
2730 DLLLOCAL
void onDetach(
QoreProgram* pgm, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
2732 AutoQoreCounterDec ad(&debug_program_counter);
2733 dpgm->onDetach(pgm, rs, rts, xsink);
2743 DLLLOCAL
void onStep(
QoreProgram* pgm,
const StatementBlock* blockStatement,
const AbstractStatement* statement,
2744 unsigned bkptId,
int& flow, DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink) {
2745 AutoQoreCounterDec ad(&debug_program_counter);
2746 dpgm->onStep(pgm, blockStatement, statement, bkptId, flow, rs, rts, xsink);
2749 DLLLOCAL
void onFunctionEnter(
QoreProgram* pgm,
const StatementBlock* statement, DebugRunStateEnum& rs,
2751 AutoQoreCounterDec ad(&debug_program_counter);
2752 dpgm->onFunctionEnter(pgm, statement, rs, rts, xsink);
2758 DLLLOCAL
void onFunctionExit(
QoreProgram* pgm,
const StatementBlock* statement,
QoreValue& returnValue,
2759 DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink) {
2760 AutoQoreCounterDec ad(&debug_program_counter);
2761 dpgm->onFunctionExit(pgm, statement, returnValue, rs, rts, xsink);
2766 DLLLOCAL
void onException(
QoreProgram* pgm,
const AbstractStatement* statement, DebugRunStateEnum& rs,
2768 AutoQoreCounterDec ad(&debug_program_counter);
2769 dpgm->onException(pgm, statement, rs, rts, xsink);
2774 DLLLOCAL
void onExit(
QoreProgram* pgm,
const StatementBlock* statement,
QoreValue& returnValue,
2775 DebugRunStateEnum& rs,
const AbstractStatement*& rts,
ExceptionSink* xsink) {
2776 AutoQoreCounterDec ad(&debug_program_counter);
2777 dpgm->onExit(pgm, statement, returnValue, rs, rts, xsink);
2780 DLLLOCAL
int breakProgramThread(
QoreProgram* pgm,
int tid) {
2787 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2788 printd(5,
"qore_debug_program_private::breakProgramThread(), this: %p, pgm: %p, i: %p, end: %p, tid: %d\n",
2789 this, pgm, i, qore_program_map.end(), tid);
2790 if (i == qore_program_map.end())
2792 if (i->second->breakProgramThread(tid))
2804 qore_program_map_t::iterator i = qore_program_map.find(pgm);
2805 printd(5,
"qore_debug_program_private::breakProgram(), this: %p, pgm: %p, i: %p, end: %p\n",
this, pgm, i,
2806 qore_program_map.end());
2807 if (i == qore_program_map.end())
2809 i->second->breakProgram();
2813 DLLLOCAL
void waitForTerminationAndClear(
ExceptionSink* xsink) {
2814 removeAllPrograms();
2819 DLLLOCAL
int getInterruptedCount() {
2820 return debug_program_counter.
getCount();
2827 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:135
#define PO_FREE_OPTIONS
mask of options that have no effect on code access or code safety
Definition: Restrictions.h:139
#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:105
provides a safe and exception-safe way to hold write locks in Qore, only to be used on the stack,...
Definition: QoreRWLock.h:144
Class implementing breakpoint for debugging.
Definition: QoreProgram.h: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:257
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:44
DLLLOCAL void set(T *ptr)
sets the key's value
Definition: QoreThreadLocalStorage.h:82
DLLLOCAL T * get()
retrieves the key's value
Definition: QoreThreadLocalStorage.h:77
provides a mutually-exclusive thread lock
Definition: QoreThreadLock.h:49
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:109
the root namespace of a QoreProgram object
Definition: QoreNamespace.h:397
Helps dereference values outside of locks.
Definition: QoreLibIntern.h:540
DLLLOCAL void add(QoreValue v)
adds a value for dereferencing on exit
Definition: QoreLibIntern.h:565
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:1191
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:1232
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:238
std::set< int > int_set_t
set of integers
Definition: common.h:82
long long int64
64bit integer type, cannot use int64_t here since it breaks the API on some 64-bit systems due to equ...
Definition: common.h:260
DLLEXPORT QoreProgram * getProgram()
returns the current QoreProgram
DLLEXPORT 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