1 //=============================================================================
2 //
3 //   File : KviKvsKernel.cpp
4 //   Creation date : Tue 30 Sep 2003 05.12 CEST 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 "KviKvsKernel.h"
26 #include "KviKvsParser.h"
27 #include "KviKvsHash.h"
28 #include "KviKvsAliasManager.h"
29 #include "KviKvsCoreSimpleCommands.h"
30 #include "KviKvsCoreFunctions.h"
31 #include "KviKvsCoreCallbackCommands.h"
32 #include "KviKvsSwitchList.h"
33 #include "KviKvsVariantList.h"
34 #include "KviKvsScript.h"
35 #include "KviKvsObjectController.h"
36 #include "KviKvsAsyncOperation.h"
37 #include "KviModuleManager.h"
38 
39 #include <QDir>
40 KviKvsKernel * KviKvsKernel::m_pKvsKernel = nullptr;
41 
42 //
43 // CONSTRUCTION AND DESTRUCTION
44 //
45 
KviKvsKernel()46 KviKvsKernel::KviKvsKernel()
47 {
48 	m_pKvsKernel = this;
49 
50 	m_pSpecialCommandParsingRoutineDict = new KviPointerHashTable<QString, KviKvsSpecialCommandParsingRoutine>(17, false);
51 	m_pSpecialCommandParsingRoutineDict->setAutoDelete(true);
52 	m_pCoreSimpleCommandExecRoutineDict = new KviPointerHashTable<QString, KviKvsCoreSimpleCommandExecRoutine>(51, false);
53 	m_pCoreSimpleCommandExecRoutineDict->setAutoDelete(true);
54 	m_pCoreFunctionExecRoutineDict = new KviPointerHashTable<QString, KviKvsCoreFunctionExecRoutine>(51, false);
55 	m_pCoreFunctionExecRoutineDict->setAutoDelete(true);
56 	m_pCoreCallbackCommandExecRoutineDict = new KviPointerHashTable<QString, KviKvsCoreCallbackCommandExecRoutine>(17, false);
57 	m_pCoreCallbackCommandExecRoutineDict->setAutoDelete(true);
58 
59 	m_pGlobalVariables = new KviKvsHash();
60 	m_pEmptyParameterList = new KviKvsVariantList();
61 	m_pObjectController = new KviKvsObjectController();
62 	m_pObjectController->init();
63 	m_pAsyncOperationManager = new KviKvsAsyncOperationManager();
64 
65 	KviKvsParser::init();
66 
67 	KviKvsCoreSimpleCommands::init();
68 	KviKvsCoreFunctions::init();
69 	KviKvsCoreCallbackCommands::init();
70 }
71 
~KviKvsKernel()72 KviKvsKernel::~KviKvsKernel()
73 {
74 	delete m_pAsyncOperationManager;
75 	delete m_pObjectController;
76 	delete m_pEmptyParameterList;
77 	delete m_pGlobalVariables;
78 
79 	delete m_pSpecialCommandParsingRoutineDict;
80 	delete m_pCoreSimpleCommandExecRoutineDict;
81 	delete m_pCoreFunctionExecRoutineDict;
82 	delete m_pCoreCallbackCommandExecRoutineDict;
83 }
84 
85 //
86 // INSTANCE MANAGEMENT
87 //
88 
init()89 void KviKvsKernel::init()
90 {
91 	if(!m_pKvsKernel)
92 		m_pKvsKernel = new KviKvsKernel();
93 }
94 
done()95 void KviKvsKernel::done()
96 {
97 	if(m_pKvsKernel)
98 	{
99 		delete m_pKvsKernel;
100 		m_pKvsKernel = nullptr;
101 	}
102 }
103 
104 #define COMPLETE_COMMAND_BY_DICT(__type, __dict)                     \
105 	{                                                                  \
106 		KviPointerHashTableIterator<QString, __type> it(*__dict);        \
107 		int l = szCommandBegin.length();                                 \
108 		while(it.current())                                              \
109 		{                                                                \
110 			if(KviQString::equalCIN(szCommandBegin, it.currentKey(), l))   \
111 				pMatches.push_back(it.currentKey());                         \
112 			++it;                                                          \
113 		}                                                                \
114 	}
115 
completeCommand(const QString & szCommandBegin,std::vector<QString> & pMatches)116 void KviKvsKernel::completeCommand(const QString & szCommandBegin, std::vector<QString> & pMatches)
117 {
118 	int idx = szCommandBegin.indexOf(QChar('.'));
119 	if(idx == -1)
120 	{
121 		// no module name inside
122 		COMPLETE_COMMAND_BY_DICT(KviKvsCoreSimpleCommandExecRoutine, m_pCoreSimpleCommandExecRoutineDict)
123 		COMPLETE_COMMAND_BY_DICT(KviKvsSpecialCommandParsingRoutine, m_pSpecialCommandParsingRoutineDict)
124 		COMPLETE_COMMAND_BY_DICT(KviKvsCoreCallbackCommandExecRoutine, m_pCoreCallbackCommandExecRoutineDict)
125 
126 		g_pModuleManager->completeModuleNames(szCommandBegin, pMatches);
127 
128 		KviKvsAliasManager::instance()->completeCommand(szCommandBegin, pMatches);
129 	}
130 	else
131 	{
132 		// contains a module name
133 		QString szModuleName = szCommandBegin.left(idx);
134 		QString szRight = szCommandBegin.right(szCommandBegin.length() - (idx + 1));
135 		completeModuleCommand(szModuleName, szRight, pMatches);
136 	}
137 }
138 
completeModuleCommand(const QString & szModuleName,const QString & szCommandBegin,std::vector<QString> & pMatches)139 void KviKvsKernel::completeModuleCommand(const QString & szModuleName, const QString & szCommandBegin, std::vector<QString> & pMatches)
140 {
141 	KviModule * pModule = g_pModuleManager->getModule(szModuleName);
142 	if(!pModule)
143 		return;
144 
145 	std::vector<QString> lModuleMatches;
146 
147 	pModule->completeCommand(szCommandBegin, lModuleMatches);
148 	for(auto & pszModuleMatch : lModuleMatches)
149 	{
150 		pszModuleMatch.prepend(".");
151 		pszModuleMatch.prepend(szModuleName);
152 		pMatches.push_back(std::move(pszModuleMatch));
153 	}
154 }
155 
completeFunction(const QString & szFunctionBegin,std::vector<QString> & pMatches)156 void KviKvsKernel::completeFunction(const QString & szFunctionBegin, std::vector<QString> & pMatches)
157 {
158 	int idx = szFunctionBegin.indexOf(QChar('.'));
159 	if(idx == -1)
160 	{
161 		// no module name inside
162 
163 		KviPointerHashTableIterator<QString, KviKvsCoreFunctionExecRoutine> it(*m_pCoreFunctionExecRoutineDict);
164 		int l = szFunctionBegin.length();
165 		while(it.current())
166 		{
167 			if(KviQString::equalCIN(szFunctionBegin, it.currentKey(), l))
168 				pMatches.push_back(it.currentKey());
169 			++it;
170 		}
171 
172 		g_pModuleManager->completeModuleNames(szFunctionBegin, pMatches);
173 
174 		std::vector<QString> lAliases;
175 
176 		KviKvsAliasManager::instance()->completeCommand(szFunctionBegin, lAliases);
177 		for(auto & pszAlias : lAliases)
178 			pMatches.push_back(std::move(pszAlias));
179 	}
180 	else
181 	{
182 		// contains a module name
183 		QString szModuleName = szFunctionBegin.left(idx);
184 		QString szRight = szFunctionBegin.right(szFunctionBegin.length() - (idx + 1));
185 		completeModuleFunction(szModuleName, szRight, pMatches);
186 	}
187 }
188 
completeModuleFunction(const QString & szModuleName,const QString & szCommandBegin,std::vector<QString> & pMatches)189 void KviKvsKernel::completeModuleFunction(const QString & szModuleName, const QString & szCommandBegin, std::vector<QString> & pMatches)
190 {
191 	KviModule * pModule = g_pModuleManager->getModule(szModuleName);
192 	if(!pModule)
193 		return;
194 
195 	std::vector<QString> lModuleMatches;
196 
197 	pModule->completeFunction(szCommandBegin, lModuleMatches);
198 	for(auto & pszModuleMatch : lModuleMatches)
199 	{
200 		pszModuleMatch.prepend(".");
201 		pszModuleMatch.prepend(szModuleName);
202 		pszModuleMatch.prepend("$");
203 		pMatches.push_back(std::move(pszModuleMatch));
204 	}
205 }
206 
getAllFunctionsCommandsCore(QStringList * list)207 void KviKvsKernel::getAllFunctionsCommandsCore(QStringList * list)
208 {
209 	KviPointerHashTableIterator<QString, KviKvsCoreFunctionExecRoutine> it(*m_pCoreFunctionExecRoutineDict);
210 	while(it.current())
211 	{
212 		list->append("$" + it.currentKey());
213 		++it;
214 	}
215 	KviPointerHashTableIterator<QString, KviKvsCoreSimpleCommandExecRoutine> it2(*m_pCoreSimpleCommandExecRoutineDict);
216 	while(it2.current())
217 	{
218 		list->append(it2.currentKey());
219 		++it2;
220 	}
221 }
222