1 //=============================================================================
2 //
3 //   File : KviKvsRunTimeContext.cpp
4 //   Creation date : Tue 07 Oct 2003 01:49:40 by Szymon Stefanek
5 //
6 //   This file is part of the KVIrc IRC client distribution
7 //   Copyright (C) 2003-2010 Szymon Stefanek <pragma at kvirc dot net>
8 //
9 //   This program is FREE software. You can redistribute it and/or
10 //   modify it under the terms of the GNU General Public License
11 //   as published by the Free Software Foundation; either version 2
12 //   of the License, or (at your option) any later version.
13 //
14 //   This program is distributed in the HOPE that it will be USEFUL,
15 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
16 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 //   See the GNU General Public License for more details.
18 //
19 //   You should have received a copy of the GNU General Public License
20 //   along with this program. If not, write to the Free Software Foundation,
21 //   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 //
23 //=============================================================================
24 
25 #include "KviKvsRunTimeContext.h"
26 #include "KviKvsScript.h"
27 #include "KviKvsKernel.h"
28 #include "KviKvsReport.h"
29 #include "KviConsoleWindow.h"
30 #include "KviKvsTreeNodeBase.h"
31 #include "KviLocale.h"
32 #include "KviApplication.h"
33 #include "KviKvsObject.h"
34 
~KviKvsExtendedRunTimeData()35 KviKvsExtendedRunTimeData::~KviKvsExtendedRunTimeData()
36 {
37 	if(m_bAutoDelete)
38 	{
39 		if(m_pExtendedScopeVariables)
40 			delete m_pExtendedScopeVariables;
41 		if(m_pAliasSwitchList)
42 			delete m_pAliasSwitchList;
43 		if(m_pThisObject)
44 			delete m_pThisObject;
45 		if(m_pScriptFilePath)
46 			delete m_pScriptFilePath;
47 		// don't delete m_pPopupId;
48 	}
49 }
50 
setPopupId(QString * pPopupId)51 void KviKvsExtendedRunTimeData::setPopupId(QString * pPopupId)
52 {
53 	m_pPopupId = pPopupId;
54 };
55 
KviKvsRunTimeContext(KviKvsScript * pScript,KviWindow * pWnd,KviKvsVariantList * pParams,KviKvsVariant * pRetVal,KviKvsExtendedRunTimeData * pExtData)56 KviKvsRunTimeContext::KviKvsRunTimeContext(KviKvsScript * pScript, KviWindow * pWnd, KviKvsVariantList * pParams, KviKvsVariant * pRetVal, KviKvsExtendedRunTimeData * pExtData)
57 {
58 	m_bError = false;
59 	m_pScript = pScript;
60 	m_pParameterList = pParams;
61 	m_pWindow = pWnd;
62 	m_pLocalVariables = new KviKvsHash();
63 	m_pReturnValue = pRetVal;
64 	m_uRunTimeFlags = 0;
65 	m_pExtendedData = pExtData;
66 	m_pDefaultReportLocation = nullptr;
67 }
68 
~KviKvsRunTimeContext()69 KviKvsRunTimeContext::~KviKvsRunTimeContext()
70 {
71 	delete m_pLocalVariables;
72 }
73 
globalVariables()74 KviKvsHash * KviKvsRunTimeContext::globalVariables()
75 {
76 	return KviKvsKernel::instance()->globalVariables();
77 }
78 
enterBlockingSection()79 void KviKvsRunTimeContext::enterBlockingSection()
80 {
81 	// actually a NO-OP
82 }
83 
leaveBlockingSection()84 bool KviKvsRunTimeContext::leaveBlockingSection()
85 {
86 	if(g_pApp->kviClosingDown())
87 		return false; // application quitting
88 	if(!g_pApp->windowExists(m_pWindow))
89 		return false; // window lost
90 	return true;
91 }
92 
swapReturnValuePointer(KviKvsVariant * pNewPointer)93 KviKvsVariant * KviKvsRunTimeContext::swapReturnValuePointer(KviKvsVariant * pNewPointer)
94 {
95 	KviKvsVariant * pAux = m_pReturnValue;
96 	m_pReturnValue = pNewPointer;
97 	return pAux;
98 }
99 
report(bool bError,KviKvsTreeNode * pNode,const QString & szMsgFmt,kvi_va_list va)100 void KviKvsRunTimeContext::report(bool bError, KviKvsTreeNode * pNode, const QString & szMsgFmt, kvi_va_list va)
101 {
102 	QString szMsg;
103 	KviQString::vsprintf(szMsg, szMsgFmt, va);
104 
105 	KviPointerList<QString> * pCodeListing = nullptr;
106 	KviPointerList<QString> * pCallStack = nullptr;
107 	QString szLocation;
108 
109 	if(pNode)
110 	{
111 		if(pNode->location() && m_pScript)
112 		{
113 			pCodeListing = new KviPointerList<QString>;
114 			pCodeListing->setAutoDelete(true);
115 
116 			int iLine, iCol;
117 
118 			KviKvsReport::findLineColAndListing(m_pScript->buffer(), pNode->location(), iLine, iCol, pCodeListing);
119 
120 			szLocation = QString(__tr2qs_ctx("line %1, near character %2", "kvs")).arg(iLine).arg(iCol);
121 		}
122 
123 		// create the call stack
124 		int iFrame = 0;
125 
126 		pCallStack = new KviPointerList<QString>;
127 		pCallStack->setAutoDelete(true);
128 
129 		while(pNode && (iFrame < 12))
130 		{
131 			QString * pString = new QString();
132 			QString szTmp;
133 			pNode->contextDescription(szTmp);
134 			*pString = QString("#%1 %2").arg(iFrame).arg(szTmp);
135 			if(pNode->location())
136 			{
137 				int iLine, iCol;
138 				KviKvsReport::findLineAndCol(m_pScript->buffer(), pNode->location(), iLine, iCol);
139 				QString tmpi = QString(" [line %1, near character %2]").arg(iLine).arg(iCol);
140 				*pString += tmpi;
141 			}
142 			pCallStack->append(pString);
143 			iFrame++;
144 			pNode = pNode->parent();
145 		}
146 		if(pNode)
147 			pCallStack->append(new QString("#12 ..."));
148 	}
149 
150 	QString szContext = m_pScript ? m_pScript->name() : "kvirc core code";
151 	KviKvsReport rep(bError ? KviKvsReport::RunTimeError : KviKvsReport::RunTimeWarning, szContext, szMsg, szLocation, m_pWindow);
152 	if(pCodeListing)
153 		rep.setCodeListing(pCodeListing);
154 	if(pCallStack)
155 		rep.setCallStack(pCallStack);
156 
157 	KviKvsReport::report(&rep, m_pWindow);
158 }
159 
error(KviKvsTreeNode * pNode,QString szMsgFmt,...)160 void KviKvsRunTimeContext::error(KviKvsTreeNode * pNode, QString szMsgFmt, ...)
161 {
162 	m_bError = true;
163 
164 	kvi_va_list va;
165 	kvi_va_start(va, szMsgFmt);
166 	report(true, pNode, szMsgFmt, va);
167 	kvi_va_end(va);
168 }
169 
warning(KviKvsTreeNode * pNode,QString szMsgFmt,...)170 void KviKvsRunTimeContext::warning(KviKvsTreeNode * pNode, QString szMsgFmt, ...)
171 {
172 	kvi_va_list va;
173 	kvi_va_start(va, szMsgFmt);
174 	report(false, pNode, szMsgFmt, va);
175 	kvi_va_end(va);
176 }
177 
error(QString szMsgFmt,...)178 void KviKvsRunTimeContext::error(QString szMsgFmt, ...)
179 {
180 	m_bError = true;
181 
182 	kvi_va_list va;
183 	kvi_va_start(va, szMsgFmt);
184 	report(true, m_pDefaultReportLocation, szMsgFmt, va);
185 	kvi_va_end(va);
186 }
187 
warning(QString szMsgFmt,...)188 void KviKvsRunTimeContext::warning(QString szMsgFmt, ...)
189 {
190 	kvi_va_list va;
191 	kvi_va_start(va, szMsgFmt);
192 	report(false, m_pDefaultReportLocation, szMsgFmt, va);
193 	kvi_va_end(va);
194 }
195 
errorNoIrcContext()196 bool KviKvsRunTimeContext::errorNoIrcContext()
197 {
198 	error(m_pDefaultReportLocation, __tr2qs_ctx("This command can be used only in windows bound to an IRC context", "kvs"));
199 	return false;
200 }
201 
warningNoIrcConnection()202 bool KviKvsRunTimeContext::warningNoIrcConnection()
203 {
204 	warning(m_pDefaultReportLocation, __tr2qs_ctx("You're not connected to an IRC server", "kvs"));
205 	return true;
206 }
207 
warningMissingParameter()208 bool KviKvsRunTimeContext::warningMissingParameter()
209 {
210 	warning(m_pDefaultReportLocation, __tr2qs_ctx("Missing parameter", "kvs"));
211 	return true;
212 }
213 
setDefaultReportLocation(KviKvsTreeNode * pNode)214 void KviKvsRunTimeContext::setDefaultReportLocation(KviKvsTreeNode * pNode)
215 {
216 	m_pDefaultReportLocation = pNode;
217 }
218