1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2015 - Scilab Enterprises - Calixte DENIZET
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 #include <fstream>
17 #include <iostream>
18 
19 #include "parser.hxx"
20 #include "prettyprintvisitor.hxx"
21 #include "SLint.hxx"
22 #include "threadmanagement.hxx"
23 #include "UTF8.hxx"
24 
25 extern "C"
26 {
27 #include "sci_malloc.h"
28 #include "os_string.h"
29 #include "expandPathVariable.h"
30 #include "localization.h"
31 #include "isdir.h"
32 #include "findfiles.h"
33 #include "freeArrayOfString.h"
34 #include "fullpath.h"
35 #include "PATH_MAX.h"
36 }
37 
38 #ifdef _MSC_VER
39 #define DEFAULT_FILESPEC L"*.*"
40 #else
41 #define DEFAULT_FILESPEC L"*"
42 #endif
43 
44 //#define SLINT_PRINT_AST
45 #ifdef SLINT_PRINT_AST
46 #include "prettyprintvisitor.hxx"
47 #endif
48 
49 namespace slint
50 {
51 
SLint(SLintOptions & options,SLintResult & result)52 SLint::SLint(SLintOptions & options, SLintResult & result) : context(*this), visitor(context, result)
53 {
54     visitor.setOptions(options);
55 }
56 
getVisitor() const57 const SLintVisitor & SLint::getVisitor() const
58 {
59     return visitor;
60 }
61 
check()62 void SLint::check()
63 {
64     visitor.getResult().handleFiles(scifiles);
65     for (const auto & scifile : scifiles)
66     {
67         context.setSciFile(scifile);
68         visitor.preCheckFile();
69 
70 #ifdef SLINT_PRINT_AST
71         ast::PrettyPrintVisitor ppv(std::wcerr, false, true);
72         scifile->getTree()->accept(ppv);
73 #undef SLINT_PRINT_AST
74 #endif
75 
76         scifile->getTree()->accept(visitor);
77         visitor.postCheckFile();
78     }
79 }
80 
setFiles(const std::wstring & files)81 void SLint::setFiles(const std::wstring & files)
82 {
83     std::vector<std::wstring> v = {files};
84     setFiles(v);
85 }
86 
setFiles(types::String * files)87 void SLint::setFiles(types::String * files)
88 {
89     const unsigned size = files->getSize();
90     std::vector<std::wstring> filesVector;
91     filesVector.reserve(size);
92 
93     for (unsigned i = 0; i < size; ++i)
94     {
95         filesVector.emplace_back(files->get(i));
96     }
97     setFiles(filesVector);
98 }
99 
setFiles(const std::vector<std::wstring> & files)100 void SLint::setFiles(const std::vector<std::wstring> & files)
101 {
102     for (const auto & file : files)
103     {
104         std::wstring full = getFullPath(file);
105         if (!visitor.getOptions().isExcluded(full))
106         {
107             if (isdirW(full.c_str()))
108             {
109                 collectInDirectory(full);
110             }
111             else if (hasSuffix(full, L".sci"))
112             {
113                 SciFilePtr sf = parseFile(full);
114                 if (sf.get())
115                 {
116                     scifiles.emplace_back(sf);
117                     context.addPublicFunction(sf->getMain());
118                 }
119             }
120         }
121     }
122 }
123 
getFiles() const124 const std::vector<SciFilePtr> & SLint::getFiles() const
125 {
126     return scifiles;
127 }
128 
collectInDirectory(const std::wstring & path)129 void SLint::collectInDirectory(const std::wstring & path)
130 {
131     std::wstring _path = path + DIR_SEPARATORW;
132     int size = -1;
133 
134     wchar_t ** files = findfilesW(_path.c_str(), DEFAULT_FILESPEC, &size, FALSE);
135     if (size > 0 && files)
136     {
137         std::vector<std::wstring> filesVector;
138         for (int i = 0; i < size; ++i)
139         {
140             filesVector.emplace_back(_path + files[i]);
141         }
142         freeArrayOfWideString(files, size);
143         setFiles(filesVector);
144     }
145 }
146 
parseFile(const std::wstring & filename)147 SciFilePtr SLint::parseFile(const std::wstring & filename)
148 {
149     std::ifstream src(scilab::UTF8::toUTF8(filename), std::ios::in | std::ios::binary | std::ios::ate);
150     if (src.is_open())
151     {
152         src.seekg(0, src.end);
153         int len = static_cast<int>(src.tellg());
154         src.seekg (0, src.beg);
155         char * buffer = new char[len + 1];
156         buffer[len] = '\0';
157         src.read(buffer, len);
158         src.close();
159 
160         wchar_t * _buffer = to_wide_string(buffer);
161         delete[] buffer;
162         Parser parser;
163 
164         ThreadManagement::LockParser();
165         parser.parse(_buffer);
166 
167         if (parser.getExitStatus() != Parser::Succeded)
168         {
169             FREE(_buffer);
170             delete parser.getTree();
171             ThreadManagement::UnlockParser();
172             throw FileException(filename, parser.getErrorMessage());
173             //return SciFilePtr(nullptr);
174         }
175         else
176         {
177             ThreadManagement::UnlockParser();
178             return SciFilePtr(new SciFile(filename, _buffer, parser.getTree()));
179         }
180     }
181 
182     wchar_t * error = to_wide_string(_("Cannot open the file"));
183     std::wstring _error(error);
184     FREE(error);
185 
186     throw FileException(filename, _error);
187 }
188 
hasSuffix(const std::wstring & filename,const std::wstring & suffix)189 bool SLint::hasSuffix(const std::wstring & filename, const std::wstring & suffix)
190 {
191     return filename.size() >= suffix.size() && filename.compare(filename.size() - suffix.size(), suffix.size(), suffix) == 0;
192 }
193 
getFullPath(const std::wstring & path)194 std::wstring SLint::getFullPath(const std::wstring & path)
195 {
196     const unsigned SIZE = PATH_MAX * 4;
197     wchar_t * expandedPath = expandPathVariableW(const_cast<wchar_t *>(path.c_str()));
198     std::wstring _fullpath;
199 
200     wchar_t * fullpath = get_full_pathW(expandedPath);
201 
202     if (fullpath)
203     {
204         FREE(expandedPath);
205         _fullpath = std::wstring(fullpath);
206     }
207     else
208     {
209         _fullpath = std::wstring(expandedPath);
210         FREE(expandedPath);
211     }
212     FREE(fullpath);
213 
214     return _fullpath;
215 }
216 } // namespace slint
217