Qore Programming Language  1.12.0
QC_DebugProgram.h
1 /* -*- mode: c++; indent-tabs-mode: nil -*- */
2 /*
3  QC_DebugProgram.h
4 
5  Qore Programming Language
6 
7  Copyright (C) 2003 - 2022 Qore Technologies, s.r.o.
8 
9  Permission is hereby granted, free of charge, to any person obtaining a
10  copy of this software and associated documentation files (the "Software"),
11  to deal in the Software without restriction, including without limitation
12  the rights to use, copy, modify, merge, publish, distribute, sublicense,
13  and/or sell copies of the Software, and to permit persons to whom the
14  Software is furnished to do so, subject to the following conditions:
15 
16  The above copyright notice and this permission notice shall be included in
17  all copies or substantial portions of the Software.
18 
19  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25  DEALINGS IN THE SOFTWARE.
26 
27  Note that the Qore library is released under a choice of three open-source
28  licenses: MIT (as above), LGPL 2+, or GPL 2+; see README-LICENSE for more
29  information.
30 */
31 
32 #ifndef _QORE_CLASS_DEBUGPROGRAM_H
33 
34 #define _QORE_CLASS_DEBUGPROGRAM_H
35 
36 DLLEXPORT extern qore_classid_t CID_DEBUGPROGRAM;
37 DLLLOCAL extern QoreClass* QC_DEBUGPROGRAM;
38 DLLLOCAL QoreClass *initDebugProgramClass(QoreNamespace& ns);
39 
40 #include <qore/QoreDebugProgram.h>
41 #include <qore/ReferenceArgumentHelper.h>
42 
43 // class needed to handle calls from C++ to Qore script instance
44 class QoreDebugProgramWithQoreObject: public QoreDebugProgram {
45 private:
46  QoreObject* qo;
47 
48  DLLLOCAL void callMethod(const char* name, QoreProgram *pgm, int paramCount, QoreValue* params, DebugRunStateEnum &rs, const AbstractStatement* &rts, ExceptionSink* xsink, ExceptionSink &xsink2) {
49  ReferenceHolder<QoreListNode> args(new QoreListNode(autoTypeInfo), &xsink2);
50  args->push(QoreProgram::getQoreObject(pgm), nullptr);
51  for (int i=0; i<paramCount; i++) {
52  //printd(5, "QoreDebugProgramWithCoreObject::callMethod(%s) this: %p, param: %d/%d, type: %s\n", name, this, i, paramCount, params[i]?params[i]->getTypeName():"n/a");
53  args->push(params[i], nullptr);
54  }
55  // LocalVar will sanitize and discard non-node values so we cannot use the ReferenceHolder
56  ReferenceArgumentHelper rsah(rs, &xsink2);
57  args->push(rsah.getArg(), nullptr); // caller owns ref
58  int sid = rts ? pgm->getStatementId(rts) : 0;
59  ReferenceArgumentHelper rtsah(sid, &xsink2);
60  args->push(rtsah.getArg(), nullptr); // caller owns ref
61  printd(5, "QoreDebugProgramWithCoreObject::callMethod(%s) this: %p, pgm: %p, param#: %d, rs: %d, rts: %d, xsink2: %d\n", name, this, pgm, paramCount, rs, sid, xsink2.isEvent());
62  qo->evalMethod(name, *args, &xsink2);
63  QoreValue rsv(rsah.getOutputValue());
64  rs = (DebugRunStateEnum) rsv.getAsBigInt();
65  rsv.discard(&xsink2);
66 
67  QoreValue rtsv(rtsah.getOutputValue());
68  sid = rtsv.getAsBigInt();
69  rtsv.discard(&xsink2);
70  if (sid <= 0) {
71  rts = nullptr;
72  } else {
73  rts = pgm->resolveStatementId(sid);
74  }
75 
76  //printd(5, "QoreDebugProgramWithCoreObject::callMethod(%s) this: %p, pgm: %p, rs: %d\n", name, this, pgm, rs);
77  /* catch all exceptions from debug code, optionally we could assimilate on demand or create exception handler
78  * but developer can try/catch by himself to handle it
79  */
80  // xsink->assimilate(xsink2);
81  }
82 
83 public:
84  DLLLOCAL QoreDebugProgramWithQoreObject(QoreObject* n_qo): qo(n_qo) {
85  //printd(5, "QoreDebugProgramWithCoreObject::QoreDebugProgramWithCoreObject() this: %p, qo: %p\n", this, n_qo);
86  }
87  DLLLOCAL virtual void onAttach(QoreProgram *pgm, DebugRunStateEnum &rs, const AbstractStatement* &rts, ExceptionSink* xsink) {
88  //printd(5, "QoreDebugProgramWithCoreObject::onAttach() this: %p, pgm: %p\n", this, pgm);
89  ExceptionSink xsink2;
90  callMethod("onAttach", pgm, 0, 0, rs, rts, xsink, xsink2);
91  }
92  DLLLOCAL virtual void onDetach(QoreProgram *pgm, DebugRunStateEnum &rs, const AbstractStatement* &rts, ExceptionSink* xsink) {
93  printd(5, "QoreDebugProgramWithCoreObject::onDetach() this: %p, pgm: %p\n", this, pgm);
94  ExceptionSink xsink2;
95  callMethod("onDetach", pgm, 0, 0, rs, rts, xsink, xsink2);
96  }
97  DLLLOCAL virtual void onStep(QoreProgram *pgm, const StatementBlock *blockStatement, const AbstractStatement *statement, unsigned bkptId, int &flow, DebugRunStateEnum &rs, const AbstractStatement* &rts, ExceptionSink* xsink) {
98  ExceptionSink xsink2;
99  QoreValue params[4];
100  params[0] = pgm->getStatementId(blockStatement);
101  params[1] = statement ? QoreValue(pgm->getStatementId(statement)) : QoreValue();
102  /*
103  if (!params[0]->getAsInt())
104  printd(5, "QoreDebugProgramWithCoreObject::onStep::blockStatement:%s:%d-%d:%s\n", blockStatement->loc.getFile(), blockStatement->loc.start_line, blockStatement->loc.end_line, typeid(blockStatement).name());
105  if (statement && !params[1]->getAsInt()) {
106  printd(5, "QoreDebugProgramWithCoreObject::onStep::statement:%s:%d-%d:%s\n", statement->loc.getFile(), statement->loc.start_line, statement->loc.end_line, typeid(statement).name());
107  }*/
108  params[2] = bkptId > 0 ? QoreValue(bkptId) : QoreValue();
109  // LocalVar will sanitize and discard non-node values so we cannot use the ReferenceHolder
110  ReferenceArgumentHelper rah(flow, &xsink2);
111  params[3] = rah.getArg(); // caller owns ref
112  callMethod("onStep", pgm, 4, params, rs, rts, xsink, xsink2);
113  QoreValue v(rah.getOutputValue());
114  flow = v.getAsBigInt();
115  v.discard(&xsink2);
116  }
117  DLLLOCAL virtual void onFunctionEnter(QoreProgram *pgm, const StatementBlock *blockStatement, DebugRunStateEnum &rs, const AbstractStatement* &rts, ExceptionSink* xsink) {
118  ExceptionSink xsink2;
119  QoreValue params[1];
120  params[0] = pgm->getStatementId(blockStatement);
121  /*
122  if (!params[0]->getAsInt())
123  printd(5, "QoreDebugProgramWithCoreObject::onFunctionEnter::blockStatement:%s:%d-%d:%s\n", blockStatement->loc.getFile(), blockStatement->loc.start_line, blockStatement->loc.end_line, typeid(blockStatement).name());
124  */
125  callMethod("onFunctionEnter", pgm, 1, params, rs, rts, xsink, xsink2);
126  }
127  DLLLOCAL virtual void onFunctionExit(QoreProgram *pgm, const StatementBlock *blockStatement, QoreValue& returnValue, DebugRunStateEnum &rs, const AbstractStatement* &rts, ExceptionSink* xsink) {
128  ExceptionSink xsink2;
129  QoreValue params[2];
130  params[0] = pgm->getStatementId(blockStatement);
131  /*
132  if (!params[0]->getAsInt())
133  printd(5, "QoreDebugProgramWithCoreObject::onFunctionExit::blockStatement:%s:%d-%d:%s\n", blockStatement->loc.getFile(), blockStatement->loc.start_line, blockStatement->loc.end_line, typeid(blockStatement).name());
134  */
135  //printd(5, "QoreDebugProgramWithCoreObject::onFunctionExit() getRetValue#0: type: %d, in: %p\n", returnValue.type, returnValue.getInternalNode());
136  ReferenceArgumentHelper rah(returnValue, &xsink2);
137  params[1] = rah.getArg(); // caller owns ref
138  callMethod("onFunctionExit", pgm, 2, params, rs, rts, xsink, xsink2);
139  returnValue = rah.getOutputValue(); // caller owns ref
140  //printd(5, "QoreDebugProgramWithCoreObject::onFunctionExit() getRetValue#3: type: %d, in: %p\n", returnValue.type, returnValue.getInternalNode());
141  }
142  DLLLOCAL virtual void onException(QoreProgram *pgm, const AbstractStatement *statement, DebugRunStateEnum &rs, const AbstractStatement* &rts, ExceptionSink* xsink) {
143  ExceptionSink xsink2;
144  QoreValue params[3];
145  params[0] = pgm->getStatementId(statement);
146  /*
147  if (!params[0]->getAsInt())
148  printd(5, "QoreDebugProgramWithCoreObject::onException::statement:%s:%d-%d:%s\n", statement->loc.getFile(), statement->loc.start_line, statement->loc.end_line, typeid(statement).name());
149  */
150  QoreException* except = xsink->getException();
151  params[1] = except->makeExceptionObject();
152  // LocalVar will sanitize and discard non-node values so we cannot use the ReferenceHolder
153  ReferenceArgumentHelper rah(QoreValue(false), &xsink2);
154  params[2] = rah.getArg(); // caller owns ref
155  callMethod("onException", pgm, 3, params, rs, rts, xsink, xsink2);
156  QoreValue v(rah.getOutputValue());
157  if (v.getAsBool()) {
158  xsink->clear(); // dismiss exception
159  }
160  v.discard(&xsink2);
161  }
162  DLLLOCAL virtual void onExit(QoreProgram *pgm, const StatementBlock *blockStatement, QoreValue& returnValue, DebugRunStateEnum &rs, const AbstractStatement* &rts, ExceptionSink* xsink) {
163  ExceptionSink xsink2;
164  QoreValue params[2];
165  params[0] = pgm->getStatementId(blockStatement);
166  /*
167  if (!params[0]->getAsInt())
168  printd(5, "QoreDebugProgramWithCoreObject::onExit::blockStatement:%s:%d-%d:%s\n", blockStatement->loc.getFile(), blockStatement->loc.start_line, blockStatement->loc.end_line, typeid(blockStatement).name());
169  */
170  //printd(5, "QoreDebugProgramWithCoreObject::onExit() getRetValue#0: type: %d, in: %p\n", returnValue.type, returnValue.getInternalNode());
171  ReferenceArgumentHelper rah(returnValue, &xsink2);
172  params[1] = rah.getArg(); // caller owns ref
173  callMethod("onExit", pgm, 2, params, rs, rts, xsink, xsink2);
174  returnValue = rah.getOutputValue(); // caller owns ref
175  //printd(5, "QoreDebugProgramWithCoreObject::onExit() getRetValue#3: type: %d, in: %p\n", returnValue.type, returnValue.getInternalNode());
176  }
177 };
178 
179 
180 #endif // _QORE_CLASS_DEBUGPROGRAM_H
container for holding Qore-language exception information and also for registering a "thread_exit" ca...
Definition: ExceptionSink.h:48
DLLEXPORT bool isEvent() const
returns true if at least one exception is present or thread_exit has been triggered
DLLEXPORT void clear()
deletes the exception list immediately
defines a Qore-language class
Definition: QoreClass.h:249
supports parsing and executing Qore-language code, reference counted, dynamically-allocated only
Definition: QoreDebugProgram.h:66
virtual DLLEXPORT void onFunctionEnter(QoreProgram *pgm, const StatementBlock *statement, DebugRunStateEnum &rs, const AbstractStatement *&rts, ExceptionSink *xsink)
virtual DLLEXPORT void onStep(QoreProgram *pgm, const StatementBlock *blockStatement, const AbstractStatement *statement, unsigned bkptId, int &flow, DebugRunStateEnum &rs, const AbstractStatement *&rts, ExceptionSink *xsink)
virtual DLLEXPORT void onFunctionExit(QoreProgram *pgm, const StatementBlock *statement, QoreValue &returnValue, DebugRunStateEnum &rs, const AbstractStatement *&rts, ExceptionSink *xsink)
virtual DLLEXPORT void onExit(QoreProgram *pgm, const StatementBlock *statement, QoreValue &returnValue, DebugRunStateEnum &rs, const AbstractStatement *&rts, ExceptionSink *xsink)
virtual DLLEXPORT void onException(QoreProgram *pgm, const AbstractStatement *statement, DebugRunStateEnum &rs, const AbstractStatement *&rts, ExceptionSink *xsink)
This is the list container type in Qore, dynamically allocated only, reference counted.
Definition: QoreListNode.h:52
contains constants, classes, and subnamespaces in QoreProgram objects
Definition: QoreNamespace.h:65
the implementation of Qore's object data type, reference counted, dynamically-allocated only
Definition: QoreObject.h:60
DLLEXPORT QoreValue evalMethod(const QoreString *name, const QoreListNode *args, ExceptionSink *xsink)
evaluates the given method with the arguments passed and returns the return value,...
supports parsing and executing Qore-language code, reference counted, dynamically-allocated only
Definition: QoreProgram.h:127
static DLLEXPORT QoreObject * getQoreObject(QoreProgram *pgm)
get QoreObject of QoreProgram
DLLEXPORT unsigned long getStatementId(const AbstractStatement *statement) const
get the statement id
DLLEXPORT AbstractStatement * resolveStatementId(unsigned long statementId) const
get the statement from statement id
allows a reference to be passed as an argument to Qore code
Definition: ReferenceArgumentHelper.h:58
unsigned qore_classid_t
used for the unique class ID for QoreClass objects
Definition: common.h:79
The main value class in Qore, designed to be passed by value.
Definition: QoreValue.h:275