fix valgrind issues during ast serialization
[scilab.git] / scilab / modules / io / sci_gateway / cpp / sci_genlib.cpp
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2006 - INRIA - Allan CORNET
4 *
5 7* 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 #define DEFAULT_ENCODING "UTF-8"
18
19 #define FILE_SEPARATOR L"/"
20
21 //XML API
22 #include <libxml/xpath.h>
23 #include <libxml/xmlwriter.h>
24
25 #include <string.h>
26 #include "parser.hxx"
27 #include "context.hxx"
28 #include "io_gw.hxx"
29 #include "scilabWrite.hxx"
30 #include "expandPathVariable.h"
31 #include "configvariable.hxx"
32 #include "string.hxx"
33 #include "library.hxx"
34 #include "macrofile.hxx"
35 #include "serializervisitor.hxx"
36
37 extern "C"
38 {
39 #include "setenvvar.h"
40 #include "sci_malloc.h"
41 #include "localization.h"
42 #include "PATH_MAX.h"
43 #include "findfiles.h"
44 #include "FileExist.h"
45 #include "deleteafile.h"
46 #include "os_swprintf.h"
47 #include "splitpath.h"
48 #include "os_wfopen.h"
49 #include "sciprint.h"
50 #include "freeArrayOfString.h"
51 }
52
53
54 xmlTextWriterPtr openXMLFile(const wchar_t *_pstFilename, const wchar_t* _pstLibName);
55 void closeXMLFile(xmlTextWriterPtr _pWriter);
56 bool AddMacroToXML(xmlTextWriterPtr _pWriter, pair<wstring, wstring> _pair);
57
58
59 using namespace types;
60 /*--------------------------------------------------------------------------*/
61 Function::ReturnValue sci_genlib(types::typed_list &in, int _iRetCount, types::typed_list &out)
62 {
63     wchar_t pstParseFile[PATH_MAX + FILENAME_MAX];
64     wchar_t pstVerbose[65535];
65
66     int iNbFile             = 0;
67     wchar_t *pstParsePath      = NULL;
68     int iParsePathLen           = 0;
69     wchar_t* pstLibName         = NULL;
70     bool bVerbose           = false;
71
72     if (in.size() < 2 && in.size() > 4)
73     {
74         return Function::Error;
75     }
76
77     //param 1, library name
78     InternalType* pIT = in[0];
79     if (pIT->isString() == false)
80     {
81         return Function::Error;
82     }
83
84     String *pS = pIT->getAs<types::String>();
85     if (pS->getSize() != 1)
86     {
87         return Function::Error;
88     }
89     pstLibName = pS->get(0);
90
91     //param 2, library path
92     pIT = in[1];
93     if (pIT->isString() == false)
94     {
95         return Function::Error;
96     }
97
98     pS = pIT->getAs<types::String>();
99     if (pS->isScalar() == false)
100     {
101         return Function::Error;
102     }
103
104     if (in.size() > 2)
105     {
106         //force flag, do nothing but keep for compatibility
107     }
108
109     if (in.size() > 3)
110     {
111         //versbose flag
112         pIT = in[3];
113         if (pIT->isBool() == false)
114         {
115             return Function::Error;
116         }
117
118         bVerbose = pIT->getAs<types::Bool>()->get()[0] == 1;
119     }
120
121     wchar_t* pstFile = pS->get(0);
122     pstParsePath = expandPathVariableW(pstFile);
123
124     os_swprintf(pstParseFile, PATH_MAX + FILENAME_MAX, L"%ls%lslib", pstParsePath, FILE_SEPARATOR);
125
126     if (bVerbose)
127     {
128         os_swprintf(pstVerbose, 65535, _W("-- Creation of [%ls] (Macros) --\n").c_str(), pstLibName);
129
130         //save current prompt mode
131         int oldVal = ConfigVariable::getPromptMode();
132         //set mode silent for errors
133         ConfigVariable::setPromptMode(0);
134         scilabWriteW(pstVerbose);
135         //restore previous prompt mode
136         ConfigVariable::setPromptMode(oldVal);
137     }
138
139     if (FileExistW(pstParseFile))
140     {
141         deleteafileW(pstParseFile);
142     }
143
144     xmlTextWriterPtr pWriter = openXMLFile(pstParseFile, pstLibName);
145
146     if (pWriter == NULL)
147     {
148         os_swprintf(pstVerbose, 65535, _W("%ls: Cannot open file ''%ls''.\n").c_str(), L"genlib", pstParseFile);
149         scilabWriteW(pstVerbose);
150
151         out.push_back(new Bool(0));
152         FREE(pstParsePath);
153         return Function::OK;
154     }
155
156
157     wchar_t **pstPath = findfilesW(pstParsePath, L"*.sci", &iNbFile, FALSE);
158
159     if (pstPath)
160     {
161         types::Library* pLib = new types::Library(pstParsePath);
162         for (int k = 0 ; k < iNbFile ; k++)
163         {
164             //version with direct parsing
165             //parse the file to find all functions
166             wstring stFullPath = wstring(pstParsePath) + wstring(FILE_SEPARATOR) + wstring(pstPath[k]);
167             wstring stFullPathBin(stFullPath);
168             stFullPathBin.replace(stFullPathBin.end() - 3, stFullPathBin.end(), L"bin");
169             wstring pstPathBin(pstPath[k]);
170             pstPathBin.replace(pstPathBin.end() - 3, pstPathBin.end(), L"bin");
171
172             //sciprint(_("%ls: Processing file: %ls\n"), L"genlib", pstPath[k]);
173
174             Parser parser;
175             parser.parseFile(stFullPath, ConfigVariable::getSCIPath());
176             if (parser.getExitStatus() !=  Parser::Succeded)
177             {
178                 os_swprintf(pstVerbose, 65535, _W("%ls: Warning: Error in file %ls : %ls. File ignored\n").c_str(), L"genlib", pstPath[k], parser.getErrorMessage());
179                 scilabWriteW(pstVerbose);
180                 delete parser.getTree();
181                 continue;
182             }
183
184             //serialize ast
185             ast::SerializeVisitor* s = new ast::SerializeVisitor(parser.getTree());
186
187             unsigned char* serialAst = s->serialize();
188             // Header is : buffer size (4 bytes) + scilab version (4 bytes)
189             unsigned int size = *((unsigned int*)serialAst);
190
191             FILE* f = os_wfopen(stFullPathBin.c_str(), L"wb");
192             fwrite(serialAst, 1, size, f);
193             fclose(f);
194             std::list<ast::Exp *>::iterator j;
195             std::list<ast::Exp *>LExp = ((ast::SeqExp*)parser.getTree())->exps_get();
196
197             for (j = LExp.begin() ; j != LExp.end() ; j++)
198             {
199                 ast::FunctionDec* pFD = dynamic_cast<ast::FunctionDec*>(*j);
200                 if (pFD)
201                 {
202                     if (AddMacroToXML(pWriter, pair<wstring, wstring>(pFD->name_get().name_get(), pstPathBin)) == false)
203                     {
204                         os_swprintf(pstVerbose, 65535, _W("%ls: Warning: %ls information cannot be added to file %ls. File ignored\n").c_str(), L"genlib", pFD->name_get().name_get().c_str(), pstPath[k]);
205                         scilabWriteW(pstVerbose);
206                     }
207
208                     pLib->add(pFD->name_get().name_get(), new types::MacroFile(pFD->name_get().name_get(), stFullPathBin, pstLibName));
209                 }
210             }
211
212             free(serialAst);
213             delete parser.getTree();
214         }
215
216         symbol::Context::getInstance()->put(symbol::Symbol(pstLibName), pLib);
217     }
218
219     freeArrayOfWideString(pstPath, iNbFile);
220     out.push_back(new Bool(1));
221     FREE(pstParsePath);
222     closeXMLFile(pWriter);
223     return Function::OK;
224 }
225
226 void closeXMLFile(xmlTextWriterPtr _pWriter)
227 {
228     int iLen;
229
230     //close opened nodes
231     iLen = xmlTextWriterEndElement(_pWriter);
232     if (iLen < 0)
233     {
234         return;
235     }
236
237     //close document
238     iLen = xmlTextWriterEndDocument(_pWriter);
239     if (iLen < 0)
240     {
241         return;
242     }
243
244     //close xml writer
245     xmlFreeTextWriter(_pWriter);
246 }
247
248 xmlTextWriterPtr openXMLFile(const wchar_t *_pstFilename, const wchar_t* _pstLibName)
249 {
250     int iLen;
251     xmlTextWriterPtr pWriter = NULL;;
252     char *pstFilename = wide_string_to_UTF8(_pstFilename);
253     char *pstLibName = wide_string_to_UTF8(_pstLibName);
254
255
256     //create a writer
257     pWriter = xmlNewTextWriterFilename(pstFilename, 0);
258     if (pWriter == NULL)
259     {
260         return NULL;
261     }
262
263     //setup indentation
264     xmlTextWriterSetIndent (pWriter, 1);
265     xmlTextWriterSetIndentString (pWriter, (xmlChar*)"  ");
266
267     //create a new document
268     iLen = xmlTextWriterStartDocument(pWriter, NULL, DEFAULT_ENCODING, "no");
269     if (iLen < 0)
270     {
271         return NULL;
272     }
273
274     //add a node "scilablib"
275     iLen = xmlTextWriterStartElement(pWriter, (xmlChar*)"scilablib");
276     if (iLen < 0)
277     {
278         return NULL;
279     }
280
281     //Add attribute "name"
282     iLen = xmlTextWriterWriteAttribute(pWriter, (xmlChar*)"name", (xmlChar*)pstLibName);
283     if (iLen < 0)
284     {
285         return NULL;
286     }
287
288     FREE(pstFilename);
289     FREE(pstLibName);
290
291     return pWriter;
292 }
293
294 bool AddMacroToXML(xmlTextWriterPtr _pWriter, pair<wstring, wstring> _pair)
295 {
296     int iLen;
297
298     if (_pWriter == NULL)
299     {
300         return false;
301     }
302
303     //create node "macro"
304     iLen = xmlTextWriterStartElement(_pWriter, (xmlChar*)"macro");
305     if (iLen < 0)
306     {
307         return false;
308     }
309
310     //Add attribute "name"
311     char* pstFirst = wide_string_to_UTF8(_pair.first.c_str());
312     iLen = xmlTextWriterWriteAttribute(_pWriter, (xmlChar*)"name", (xmlChar*)pstFirst);
313     if (iLen < 0)
314     {
315         return false;
316     }
317     FREE(pstFirst);
318
319     //Add attribute "file"
320     char* pstSecond = wide_string_to_UTF8(_pair.second.c_str());
321     iLen = xmlTextWriterWriteAttribute(_pWriter, (xmlChar*)"file", (xmlChar*)pstSecond);
322     if (iLen < 0)
323     {
324         return false;
325     }
326     FREE(pstSecond);
327
328     //close "macro" node
329     iLen = xmlTextWriterEndElement(_pWriter);
330     if (iLen < 0)
331     {
332         return false;
333     }
334     return true;
335 }