c2761746f7513c8efce4c10b5119a2eafe06654d
[scilab.git] / scilab / modules / functions_manager / src / cpp / funcmanager.cpp
1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2008-2008 - DIGITEO - Antoine ELIAS
4 *
5  * Copyright (C) 2012 - 2016 - Scilab Enterprises
6  *
7  * This file is hereby licensed under the terms of the GNU GPL v2.0,
8  * pursuant to article 5.3.4 of the CeCILL v.2.1.
9  * This file was originally licensed under the terms of the CeCILL v2.1,
10  * and continues to be available under such terms.
11  * For more information, see the COPYING file which you should have received
12  * along with this program.
13 *
14 */
15
16 #ifdef _MSC_VER
17 #pragma warning(disable : 4996) //It's not beautifull but that works !
18 #endif
19
20
21 //#include <iostream>
22 #include <fstream>
23 //#include <sstream>
24
25 //XML API
26 #include <libxml/xpath.h>
27 #include <libxml/xmlreader.h>
28
29 #include "sci_malloc.h"
30 #include "funcmanager.hxx"
31 #include "execvisitor.hxx"
32 #include "configvariable.hxx"
33 #include "module_declaration.hxx"
34 #include "parser.hxx"
35
36 extern "C"
37 {
38 #include "findfiles.h"
39 #include "configvariable_interface.h"
40 #include "os_string.h"
41 }
42
43 #define BASENAMEMODULESFILE L"etc/modules.xml"
44
45 bool FileExist(std::string _szFile);
46 bool FileExist(std::wstring _szFile);
47 char *GetXmlFileEncoding(const std::string& _filename);
48
49 FuncManager* FuncManager::me = NULL;
50
51 FuncManager* FuncManager::getInstance()
52 {
53     if (me == NULL)
54     {
55         me = new FuncManager();
56         me->CreateModuleList();
57         /*get module activation list from xml file*/
58         if (me->GetModules() == true)
59         {
60             if (me->AppendModules() == false)
61             {
62                 destroyInstance();
63                 return NULL;
64             }
65         }
66         else
67         {
68             destroyInstance();
69             return NULL;
70         }
71     }
72
73     return me;
74 }
75
76 void FuncManager::destroyInstance()
77 {
78     if (me)
79     {
80         delete me;
81         me = NULL;
82     }
83 }
84
85 FuncManager::FuncManager(void)
86 {
87     m_bNoStart = false;
88 }
89
90 FuncManager::~FuncManager(void)
91 {
92 }
93
94 bool FuncManager::GetModules()
95 {
96     std::wstring szModulesFilename;
97
98     std::wstring szPath = ConfigVariable::getSCIPath();
99     if (szPath == L"")
100     {
101         std::wcout << L"The SCI environment variable is not set." << std::endl;
102         return false;
103     }
104
105     szModulesFilename = szPath + L"/";
106     szModulesFilename += BASENAMEMODULESFILE;
107
108     if (FileExist(szModulesFilename))
109     {
110         m_szXmlFile = szModulesFilename;
111     }
112     else
113     {
114         std::wcout << L"Cannot load the module declaration file: " << szModulesFilename << std::endl;
115         return false;
116     }
117     return true;
118 }
119
120 bool FuncManager::AppendModules()
121 {
122     char* pstTemp = wide_string_to_UTF8(m_szXmlFile.c_str());
123
124     char *encoding = GetXmlFileEncoding(pstTemp);
125
126     /* Don't care about line return / empty line */
127     xmlKeepBlanksDefault(0);
128     /* check if the XML file has been encoded with utf8 (unicode) or not */
129     if (stricmp("utf-8", encoding) == 0)
130     {
131         xmlDocPtr doc;
132         xmlXPathContextPtr xpathCtxt    = NULL;
133         xmlXPathObjectPtr xpathObj              = NULL;
134         char *name                                                                              = NULL;
135         int activate                                                                    = 0;
136
137         doc = xmlParseFile (pstTemp);
138
139         if (doc == NULL)
140         {
141             std::cout << "Error: Could not parse file " << pstTemp << std::endl;
142             if (encoding)
143             {
144                 free(encoding);
145                 encoding = NULL;
146             }
147             FREE(pstTemp);
148             return false;
149         }
150
151         xpathCtxt = xmlXPathNewContext(doc);
152         xpathObj = xmlXPathEval((const xmlChar*)"//modules/module", xpathCtxt);
153
154         if (xpathObj && xpathObj->nodesetval->nodeMax)
155         {
156             /* the Xpath has been understood and there are node */
157             for (int    i = 0 ; i < xpathObj->nodesetval->nodeNr ; i++)
158             {
159
160                 xmlAttrPtr attrib = xpathObj->nodesetval->nodeTab[i]->properties;
161                 /* Get the properties of <module>  */
162                 while (attrib != NULL)
163                 {
164                     /* loop until when have read all the attributes */
165                     if (xmlStrEqual (attrib->name, (const xmlChar*)"name"))
166                     {
167                         /* we found the tag name */
168                         const char *str = (const char*)attrib->children->content;
169                         name = os_strdup(str);
170                     }
171                     else if (xmlStrEqual(attrib->name, (const xmlChar*)"activate"))
172                     {
173                         /* we found the tag activate */
174                         const char *str = (const char*)attrib->children->content;
175                         if (stricmp(str, "yes") == 0 || strcmp(str, "1") == 0)
176                         {
177                             activate = 1;
178                         }
179                     }
180                     attrib = attrib->next;
181                 }
182
183                 if ((name) && (strlen(name) > 0) && (activate))
184                 {
185                     wchar_t* pstName = to_wide_string(name);
186                     if (VerifyModule(pstName))
187                     {
188                         m_ModuleName.push_back(pstName);
189                     }
190                     else
191                     {
192                         std::wcout << pstName << " module not found." << std::endl;
193                     }
194                     FREE(pstName);
195                 }
196
197                 if (name)
198                 {
199                     free(name);
200                     name = NULL;
201                 }
202                 activate = 0;
203             }
204         }
205
206         if (xpathObj)
207         {
208             xmlXPathFreeObject(xpathObj);
209         }
210         if (xpathCtxt)
211         {
212             xmlXPathFreeContext(xpathCtxt);
213         }
214         xmlFreeDoc (doc);
215     }
216     else
217     {
218         std::cout << "Error: Not a valid module file " << pstTemp << " (encoding not 'utf-8') Encoding '" << encoding << "' found." << std::endl;
219     }
220     if (encoding)
221     {
222         free(encoding);
223         encoding = NULL;
224     }
225
226     ConfigVariable::setModuleList(m_ModuleName);
227     FREE(pstTemp);
228
229     return true;
230 }
231
232 bool FuncManager::VerifyModule(wchar_t* _pszModuleName)
233 {
234     std::wstring SciPath = ConfigVariable::getSCIPath();
235     if (SciPath == L"")
236     {
237         std::wcout << L"The SCI environment variable is not set." << std::endl;
238         return false;
239     }
240
241     std::wstring FullPathModuleName = SciPath + L"/modules/" + _pszModuleName + L"/etc/" + _pszModuleName + START_EXT;
242
243     /* ajouter d'autres tests d'existences */
244
245     if (!FileExist(FullPathModuleName))
246     {
247         return false;
248     }
249     return true;
250 }
251
252 /*Out of class*/
253 bool FileExist(std::string _szFile)
254 {
255     bool bReturn = false;
256     std::fstream filestr(_szFile.c_str(), std::fstream::in);
257     bReturn = !filestr.fail();
258     filestr.close();
259     return bReturn;
260 }
261
262 bool FileExist(std::wstring _szFile)
263 {
264     bool bReturn = false;
265     char *pstFile = wide_string_to_UTF8(_szFile.c_str());
266     std::wfstream filestr(pstFile, std::wfstream::in);
267     bReturn = !filestr.fail();
268     filestr.close();
269     FREE(pstFile);
270     return bReturn;
271 }
272
273 char *GetXmlFileEncoding(const std::string& _filename)
274 {
275 #define DEFAULT_ENCODING "UTF-8"
276
277     char *encoding = NULL;
278     xmlDocPtr doc = NULL;
279
280     /* default */
281     encoding = os_strdup(DEFAULT_ENCODING);
282
283     doc = xmlParseFile(_filename.c_str());
284     if (doc)
285     {
286         if (doc->encoding)
287         {
288             if (encoding)
289             {
290                 free(encoding);
291                 encoding = NULL;
292             }
293             encoding = os_strdup((char*)doc->encoding);
294         }
295     }
296
297     xmlFreeDoc(doc);
298     return encoding;
299 }
300
301 bool FuncManager::CreateModuleList(void)
302 {
303     m_ModuleMap[L"elementary_functions"] = std::pair<GW_MOD, GW_MOD>(&ElemFuncModule::Load, &ElemFuncModule::Unload);
304     m_ModuleMap[L"sparse"] = std::pair<GW_MOD, GW_MOD>(&SparseModule::Load, &SparseModule::Unload);
305     m_ModuleMap[L"boolean"] = std::pair<GW_MOD, GW_MOD>(&BooleanModule::Load, &BooleanModule::Unload);
306     m_ModuleMap[L"integer"] = std::pair<GW_MOD, GW_MOD>(&IntegerModule::Load, &IntegerModule::Unload);
307     m_ModuleMap[L"core"] = std::pair<GW_MOD, GW_MOD>(&CoreModule::Load, &CoreModule::Unload);
308     m_ModuleMap[L"io"] = std::pair<GW_MOD, GW_MOD>(&IoModule::Load, &IoModule::Unload);
309     m_ModuleMap[L"functions"] = std::pair<GW_MOD, GW_MOD>(&FunctionsModule::Load, &FunctionsModule::Unload);
310     m_ModuleMap[L"output_stream"] = std::pair<GW_MOD, GW_MOD>(&OutputStreamModule::Load, &OutputStreamModule::Unload);
311     m_ModuleMap[L"matio"] = std::pair<GW_MOD, GW_MOD>(&MatioModule::Load, &MatioModule::Unload);
312     m_ModuleMap[L"fileio"] = std::pair<GW_MOD, GW_MOD>(&FileioModule::Load, &FileioModule::Unload);
313     m_ModuleMap[L"gui"] = std::pair<GW_MOD, GW_MOD>(&GuiModule::Load, &GuiModule::Unload);
314     m_ModuleMap[L"time"] = std::pair<GW_MOD, GW_MOD>(&TimeModule::Load, &TimeModule::Unload);
315     m_ModuleMap[L"string"] = std::pair<GW_MOD, GW_MOD>(&StringModule::Load, &StringModule::Unload);
316     m_ModuleMap[L"scinotes"] = std::pair<GW_MOD, GW_MOD>(&ScinotesModule::Load, &ScinotesModule::Unload);
317     m_ModuleMap[L"localization"] = std::pair<GW_MOD, GW_MOD>(&LocalizationModule::Load, &LocalizationModule::Unload);
318     m_ModuleMap[L"helptools"] = std::pair<GW_MOD, GW_MOD>(&HelptoolsModule::Load, &HelptoolsModule::Unload);
319     m_ModuleMap[L"hdf5"] = std::pair<GW_MOD, GW_MOD>(&Hdf5Module::Load, &Hdf5Module::Unload);
320     m_ModuleMap[L"dynamic_link"] = std::pair<GW_MOD, GW_MOD>(&DynamicLinkModule::Load, &DynamicLinkModule::Unload);
321     m_ModuleMap[L"action_binding"] = std::pair<GW_MOD, GW_MOD>(&ActionBindingModule::Load, &ActionBindingModule::Unload);
322     m_ModuleMap[L"history_manager"] = std::pair<GW_MOD, GW_MOD>(&HistoryManagerModule::Load, &HistoryManagerModule::Unload);
323     m_ModuleMap[L"console"] = std::pair<GW_MOD, GW_MOD>(&ConsoleModule::Load, &ConsoleModule::Unload);
324     m_ModuleMap[L"signal_processing"] = std::pair<GW_MOD, GW_MOD>(&SignalProcessingModule::Load, &SignalProcessingModule::Unload);
325     m_ModuleMap[L"linear_algebra"] = std::pair<GW_MOD, GW_MOD>(&LinearAlgebraModule::Load, &LinearAlgebraModule::Unload);
326     m_ModuleMap[L"statistics"] = std::pair<GW_MOD, GW_MOD>(&StatisticsModule::Load, &StatisticsModule::Unload);
327     m_ModuleMap[L"differential_equations"] = std::pair<GW_MOD, GW_MOD>(&DifferentialEquationsModule::Load, &DifferentialEquationsModule::Unload);
328     m_ModuleMap[L"cacsd"] = std::pair<GW_MOD, GW_MOD>(&CacsdModule::Load, &CacsdModule::Unload);
329     m_ModuleMap[L"spreadsheet"] = std::pair<GW_MOD, GW_MOD>(&SpreadsheetModule::Load, &SpreadsheetModule::Unload);
330     m_ModuleMap[L"randlib"] = std::pair<GW_MOD, GW_MOD>(&RandlibModule::Load, &RandlibModule::Unload);
331     m_ModuleMap[L"graphics"] = std::pair<GW_MOD, GW_MOD>(&GraphicsModule::Load, &GraphicsModule::Unload);
332     m_ModuleMap[L"interpolation"] = std::pair<GW_MOD, GW_MOD>(&InterpolationModule::Load, &InterpolationModule::Unload);
333     m_ModuleMap[L"sound"] = std::pair<GW_MOD, GW_MOD>(&SoundModule::Load, &SoundModule::Unload);
334     m_ModuleMap[L"umfpack"] = std::pair<GW_MOD, GW_MOD>(&UmfpackModule::Load, &UmfpackModule::Unload);
335     m_ModuleMap[L"optimization"] = std::pair<GW_MOD, GW_MOD>(&OptimizationModule::Load, &OptimizationModule::Unload);
336     m_ModuleMap[L"special_functions"] = std::pair<GW_MOD, GW_MOD>(&SpecialFunctionsModule::Load, &SpecialFunctionsModule::Unload);
337     m_ModuleMap[L"graphic_export"] = std::pair<GW_MOD, GW_MOD>(&GraphicExportModule::Load, &GraphicExportModule::Unload);
338     m_ModuleMap[L"polynomials"] = std::pair<GW_MOD, GW_MOD>(&PolynomialsModule::Load, &PolynomialsModule::Unload);
339     m_ModuleMap[L"arnoldi"] = std::pair<GW_MOD, GW_MOD>(&ArnoldiModule::Load, &ArnoldiModule::Unload);
340     m_ModuleMap[L"data_structures"] = std::pair<GW_MOD, GW_MOD>(&DataStructuresModule::Load, &DataStructuresModule::Unload);
341     m_ModuleMap[L"call_scilab"] = std::pair<GW_MOD, GW_MOD>(&CallScilabModule::Load, &CallScilabModule::Unload);
342     m_ModuleMap[L"completion"] = std::pair<GW_MOD, GW_MOD>(&CompletionModule::Load, &CompletionModule::Unload);
343     m_ModuleMap[L"xml"] = std::pair<GW_MOD, GW_MOD>(&XmlModule::Load, &XmlModule::Unload);
344     m_ModuleMap[L"scicos"] = std::pair<GW_MOD, GW_MOD>(&ScicosModule::Load, &ScicosModule::Unload);
345     m_ModuleMap[L"xcos"] = std::pair<GW_MOD, GW_MOD>(&XcosModule::Load, &XcosModule::Unload);
346     m_ModuleMap[L"fftw"] = std::pair<GW_MOD, GW_MOD>(&FFTWModule::Load, &FFTWModule::Unload);
347     m_ModuleMap[L"mpi"] = std::pair<GW_MOD, GW_MOD>(&MPIModule::Load, &MPIModule::Unload);
348     m_ModuleMap[L"external_objects"] = std::pair<GW_MOD, GW_MOD>(&ExternalObjectsModule::Load, &ExternalObjectsModule::Unload);
349     m_ModuleMap[L"external_objects_java"] = std::pair<GW_MOD, GW_MOD>(&ExternalObjectsJavaModule::Load, &ExternalObjectsJavaModule::Unload);
350     m_ModuleMap[L"preferences"] = std::pair<GW_MOD, GW_MOD>(&PreferencesModule::Load, &PreferencesModule::Unload);
351     m_ModuleMap[L"slint"] = std::pair<GW_MOD, GW_MOD>(&SlintModule::Load, &SlintModule::Unload);
352     m_ModuleMap[L"coverage"] = std::pair<GW_MOD, GW_MOD>(&CoverageModule::Load, &SlintModule::Unload);
353
354     if (ConfigVariable::getScilabMode() != SCILAB_NWNI)
355     {
356         m_ModuleMap[L"tclsci"] = std::pair<GW_MOD, GW_MOD>(&TclsciModule::Load, &TclsciModule::Unload);
357         m_ModuleMap[L"jvm"] = std::pair<GW_MOD, GW_MOD>(&JvmModule::Load, &JvmModule::Unload);
358         m_ModuleMap[L"ui_data"] = std::pair<GW_MOD, GW_MOD>(&UiDataModule::Load, &UiDataModule::Unload);
359     }
360 #ifdef _MSC_VER
361     m_ModuleMap[L"windows_tools"] = std::pair<GW_MOD, GW_MOD>(&WindowsToolsModule::Load, &WindowsToolsModule::Unload);
362 #endif
363     return true;
364 }
365
366 bool FuncManager::ExecuteFile(const std::wstring& _stFile)
367 {
368     Parser parser;
369
370     parser.parseFile(_stFile, ConfigVariable::getSCIPath());
371
372     if (parser.getExitStatus() == Parser::Failed)
373     {
374         std::wostringstream ostr;
375         ostr << _W("Unable to execute : ") << _stFile << std::endl;
376         scilabWriteW(ostr.str().c_str());
377         delete parser.getTree();
378         return false;
379     }
380
381     //save current prompt mode
382     int oldVal = ConfigVariable::getPromptMode();
383     //set mode silent for errors
384     ConfigVariable::setPromptMode(-1);
385     try
386     {
387         ast::ExecVisitor exec;
388         parser.getTree()->accept(exec);
389     }
390     catch (const ast::InternalError& ie)
391     {
392         scilabWriteW(ie.GetErrorMessage().c_str());
393     }
394
395     //restore previous prompt mode
396     ConfigVariable::setPromptMode(oldVal);
397     delete parser.getTree();
398     return true;
399 }
400
401 bool FuncManager::LoadModules()
402 {
403     //load gateways
404     for (const auto & it : m_ModuleName)
405     {
406         ModuleMap::iterator itModule = m_ModuleMap.find(it);
407         if (itModule != m_ModuleMap.end())
408         {
409             //call ::Load function
410             itModule->second.first();
411         }
412     }
413
414     return true;
415 }
416
417 bool FuncManager::EndModules()
418 {
419     //excute .start file
420     for (const auto & it : m_ModuleName)
421     {
422         ExecuteQuitFile(it);
423     }
424
425     return true;
426 }
427
428
429 bool FuncManager::UnloadModules()
430 {
431     //load gateways
432     for (const auto & it : m_ModuleName)
433     {
434         ModuleMap::iterator itModule = m_ModuleMap.find(it);
435         if (itModule != m_ModuleMap.end())
436         {
437             //call ::Unload function
438             itModule->second.second();
439         }
440     }
441
442     //Unload shared libraries
443     int iCount = ConfigVariable::getDynModuleCount();
444     DynLibHandle* libs = ConfigVariable::getAllDynModule();
445     for (int i = 0 ; i < iCount ; i++)
446     {
447         FreeDynLibrary(libs[i]);
448     }
449
450     ConfigVariable::cleanDynModule();
451     delete[] libs;
452     return true;
453 }
454
455 bool FuncManager::ExecuteStartFile(const std::wstring& _stModule)
456 {
457     //build .start filename
458     std::wstring stPath = ConfigVariable::getSCIPath();
459     stPath += MODULE_DIR;
460     stPath += _stModule;
461     stPath += ETC_DIR;
462     stPath += _stModule;
463     stPath += START_EXT;
464
465     return ExecuteFile(stPath);
466 }
467
468 bool FuncManager::ExecuteQuitFile(const std::wstring& _stModule)
469 {
470     //build .quit filename
471     std::wstring stPath = ConfigVariable::getSCIPath();
472     stPath += MODULE_DIR;
473     stPath += _stModule;
474     stPath += ETC_DIR;
475     stPath += _stModule;
476     stPath += QUIT_EXT;
477
478     return ExecuteFile(stPath);
479 }