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