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