2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2006 - INRIA - Allan CORNET
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
14 #pragma warning(disable : 4996) //It's not beautifull but that works !
17 #define DEFAULT_ENCODING "UTF-8"
20 #define FILE_SEPARATOR L"\\"
22 #define FILE_SEPARATOR L"/"
26 #include <libxml/xpath.h>
27 #include <libxml/xmlwriter.h>
31 #include "context.hxx"
33 #include "scilabWrite.hxx"
34 #include "expandPathVariable.h"
35 #include "configvariable.hxx"
37 #include "library.hxx"
38 #include "macrofile.hxx"
39 #include "serializervisitor.hxx"
43 #include "setenvvar.h"
44 #include "sci_malloc.h"
45 #include "localization.h"
47 #include "findfiles.h"
48 #include "FileExist.h"
49 #include "deleteafile.h"
50 #include "os_string.h"
51 #include "splitpath.h"
52 #include "os_wfopen.h"
54 #include "freeArrayOfString.h"
56 #include "scicurdir.h"
61 xmlTextWriterPtr openXMLFile(const wchar_t *_pstFilename, const wchar_t* _pstLibName);
62 void closeXMLFile(xmlTextWriterPtr _pWriter);
63 bool AddMacroToXML(xmlTextWriterPtr _pWriter, pair<wstring, wstring> _pair);
66 using namespace types;
67 /*--------------------------------------------------------------------------*/
68 Function::ReturnValue sci_genlib(types::typed_list &in, int _iRetCount, types::typed_list &out)
70 wchar_t pstParseFile[PATH_MAX + FILENAME_MAX];
71 wchar_t pstVerbose[65535];
74 wchar_t *pstParsePath = NULL;
75 int iParsePathLen = 0;
76 wchar_t* pstLibName = NULL;
77 bool bVerbose = false;
79 if (in.size() < 1 || in.size() > 4)
81 Scierror(78, _("%s: Wrong number of input argument(s): %d to %d expected.\n"), "genlib", 1, 4);
82 return Function::Error;
85 //param 1, library name
86 InternalType* pIT = in[0];
87 if (pIT->isString() == false)
89 Scierror(999, _("%s: Wrong type for input argument #%d: A string expected.\n"), "genlib", 1);
90 return Function::Error;
93 String *pS = pIT->getAs<types::String>();
94 if (pS->getSize() != 1)
96 Scierror(999, _("%s: Wrong size for input argument #%d: A string expected.\n"), "genlib", 1);
97 return Function::Error;
99 pstLibName = pS->get(0);
101 //param 2, library path
105 if (pIT->isString() == false)
107 Scierror(999, _("%s: Wrong type for input argument #%d: A string expected.\n"), "genlib", 2);
108 return Function::Error;
114 pIT = new types::String(scigetcwd(&ierr));
117 pS = pIT->getAs<types::String>();
118 if (pS->isScalar() == false)
120 Scierror(999, _("%s: Wrong size for input argument #%d: A string expected.\n"), "genlib", 2);
121 return Function::Error;
126 //force flag, do nothing but keep for compatibility
133 if (pIT->isBool() == false)
135 return Function::Error;
138 bVerbose = pIT->getAs<types::Bool>()->get()[0] == 1;
141 wchar_t* pstFile = pS->get(0);
142 pstParsePath = expandPathVariableW(pstFile);
144 os_swprintf(pstParseFile, PATH_MAX + FILENAME_MAX, L"%ls%lslib", pstParsePath, FILE_SEPARATOR);
148 os_swprintf(pstVerbose, 65535, _W("-- Creation of [%ls] (Macros) --\n").c_str(), pstLibName);
150 //save current prompt mode
151 int oldVal = ConfigVariable::getPromptMode();
152 //set mode silent for errors
153 ConfigVariable::setPromptMode(0);
154 scilabWriteW(pstVerbose);
155 //restore previous prompt mode
156 ConfigVariable::setPromptMode(oldVal);
159 if (FileExistW(pstParseFile))
161 deleteafileW(pstParseFile);
164 xmlTextWriterPtr pWriter = openXMLFile(pstParseFile, pstLibName);
168 os_swprintf(pstVerbose, 65535, _W("%ls: Cannot open file ''%ls''.\n").c_str(), L"genlib", pstParseFile);
169 scilabWriteW(pstVerbose);
171 out.push_back(new Bool(0));
177 wchar_t **pstPath = findfilesW(pstParsePath, L"*.sci", &iNbFile, FALSE);
181 types::Library* pLib = new types::Library(pstParsePath);
182 for (int k = 0 ; k < iNbFile ; k++)
184 //version with direct parsing
185 //parse the file to find all functions
186 wstring stFullPath = wstring(pstParsePath) + wstring(FILE_SEPARATOR) + wstring(pstPath[k]);
187 wstring stFullPathBin(stFullPath);
188 stFullPathBin.replace(stFullPathBin.end() - 3, stFullPathBin.end(), L"bin");
189 wstring pstPathBin(pstPath[k]);
190 pstPathBin.replace(pstPathBin.end() - 3, pstPathBin.end(), L"bin");
194 sciprint(_("%ls: Processing file: %ls\n"), L"genlib", pstPath[k]);
198 parser.parseFile(stFullPath, ConfigVariable::getSCIPath());
199 if (parser.getExitStatus() != Parser::Succeded)
201 scilabWriteW(parser.getErrorMessage());
202 Scierror(999, _("%ls: Error in file %ls.\n"), L"genlib", stFullPath.data());
203 return Function::Error;
207 ast::SerializeVisitor* s = new ast::SerializeVisitor(parser.getTree());
209 unsigned char* serialAst = s->serialize();
210 // Header is : buffer size (4 bytes) + scilab version (4 bytes)
211 unsigned int size = *((unsigned int*)serialAst);
213 FILE* f = os_wfopen(stFullPathBin.c_str(), L"wb");
214 fwrite(serialAst, 1, size, f);
217 ast::exps_t LExp = parser.getTree()->getAs<ast::SeqExp>()->getExps();
218 for (ast::exps_t::iterator j = LExp.begin(), itEnd = LExp.end() ; j != itEnd ; ++j)
220 if ((*j)->isFunctionDec())
222 ast::FunctionDec* pFD = (*j)->getAs<ast::FunctionDec>();
223 const wstring& name = pFD->getSymbol().getName();
224 if (name + L".sci" == pstPath[k])
226 if (AddMacroToXML(pWriter, pair<wstring, wstring>(name, pstPathBin)) == false)
228 os_swprintf(pstVerbose, 65535, _W("%ls: Warning: %ls information cannot be added to file %ls. File ignored\n").c_str(), L"genlib", pFD->getSymbol().getName().c_str(), pstPath[k]);
229 scilabWriteW(pstVerbose);
232 pLib->add(name, new types::MacroFile(name, stFullPathBin, pstLibName));
240 delete parser.getTree();
243 symbol::Context* ctx = symbol::Context::getInstance();
244 symbol::Symbol sym = symbol::Symbol(pstLibName);
245 if (ctx->isprotected(sym) == false)
247 ctx->put(symbol::Symbol(pstLibName), pLib);
251 Scierror(999, _("Redefining permanent variable.\n"));
252 return Function::Error;
256 freeArrayOfWideString(pstPath, iNbFile);
257 out.push_back(new Bool(1));
259 closeXMLFile(pWriter);
263 void closeXMLFile(xmlTextWriterPtr _pWriter)
268 iLen = xmlTextWriterEndElement(_pWriter);
275 iLen = xmlTextWriterEndDocument(_pWriter);
282 xmlFreeTextWriter(_pWriter);
285 xmlTextWriterPtr openXMLFile(const wchar_t *_pstFilename, const wchar_t* _pstLibName)
288 xmlTextWriterPtr pWriter = NULL;;
289 char *pstFilename = wide_string_to_UTF8(_pstFilename);
290 char *pstLibName = wide_string_to_UTF8(_pstLibName);
294 pWriter = xmlNewTextWriterFilename(pstFilename, 0);
301 xmlTextWriterSetIndent (pWriter, 1);
302 xmlTextWriterSetIndentString (pWriter, (xmlChar*)" ");
304 //create a new document
305 iLen = xmlTextWriterStartDocument(pWriter, NULL, DEFAULT_ENCODING, "no");
311 //add a node "scilablib"
312 iLen = xmlTextWriterStartElement(pWriter, (xmlChar*)"scilablib");
318 //Add attribute "name"
319 iLen = xmlTextWriterWriteAttribute(pWriter, (xmlChar*)"name", (xmlChar*)pstLibName);
331 bool AddMacroToXML(xmlTextWriterPtr _pWriter, pair<wstring, wstring> _pair)
335 if (_pWriter == NULL)
340 //create node "macro"
341 iLen = xmlTextWriterStartElement(_pWriter, (xmlChar*)"macro");
347 //Add attribute "name"
348 char* pstFirst = wide_string_to_UTF8(_pair.first.c_str());
349 iLen = xmlTextWriterWriteAttribute(_pWriter, (xmlChar*)"name", (xmlChar*)pstFirst);
356 //Add attribute "file"
357 char* pstSecond = wide_string_to_UTF8(_pair.second.c_str());
358 iLen = xmlTextWriterWriteAttribute(_pWriter, (xmlChar*)"file", (xmlChar*)pstSecond);
366 iLen = xmlTextWriterEndElement(_pWriter);