Windows command.temp EACCES error.
[scilab.git] / scilab / modules / ast / src / cpp / parse / parser.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2008-2008 - INRIA - Bruno JOFRET
4  *  Copyright (C) 2010-2010 - DIGITEO - Bruno JOFRET
5  *
6  *  This file must be used under the terms of the CeCILL.
7  *  This source file is licensed as described in the file COPYING, which
8  *  you should have received as part of this distribution.  The terms
9  *  are also available at
10  *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
11  *
12  */
13
14 #include <fstream>
15 #include <string>
16 #include <string.h>
17 #include "parser.hxx"
18 #include "parser_private.hxx"
19 #include "scilabexception.hxx"
20
21 #ifdef _MSC_VER
22 #include "windows.h"
23 #include "charEncoding.h"
24 #include "sci_malloc.h"
25 #endif
26
27 extern "C"
28 {
29 #include "sci_tmpdir.h"
30 #include "Scierror.h"
31 #include "localization.h"
32 #include "os_string.h"
33 #ifdef __APPLE__
34 #include "PATH_MAX.h"
35 #endif
36 }
37
38 extern FILE*    yyin;
39 extern int      yyparse();
40 extern int      yydebug;
41 extern int      yylex_destroy();
42
43 void Parser::cleanup()
44 {
45     yylex_destroy();
46 }
47
48 void Parser::parseFile(const std::wstring& fileName, const std::wstring& progName)
49 {
50     // Calling Parse state machine in C with global values
51     // Must be locked to avoid concurrent access
52     // FIXME : LOCK
53     if (getParseTrace() == true)
54     {
55         ParserSingleInstance::enableParseTrace();
56     }
57     else
58     {
59         ParserSingleInstance::disableParseTrace();
60     }
61     ParserSingleInstance::parseFile(fileName, progName);
62     this->setExitStatus(ParserSingleInstance::getExitStatus());
63     this->setControlStatus(ParserSingleInstance::getControlStatus());
64     if (getExitStatus() == Parser::Succeded)
65     {
66         this->setTree(ParserSingleInstance::getTree());
67     }
68     else
69     {
70         this->setErrorMessage(ParserSingleInstance::getErrorMessage());
71     }
72     // FIXME : UNLOCK
73 }
74
75
76 /** \brief parse the given file name */
77 void ParserSingleInstance::parseFile(const std::wstring& fileName, const std::wstring& progName)
78 {
79     yylloc.first_line = yylloc.last_line = 1;
80     yylloc.first_column = yylloc.last_column = 1;
81 #ifdef _MSC_VER
82     _wfopen_s(&yyin, fileName.c_str(), L"r");
83 #else
84     char* pstTemp = wide_string_to_UTF8(fileName.c_str());
85     yyin = fopen(pstTemp, "r");
86     FREE(pstTemp);
87 #endif
88
89     if (!yyin)
90     {
91         wchar_t szError[bsiz];
92         os_swprintf(szError, bsiz, _W("%ls: Cannot open file %ls.\n").c_str(), L"parser", fileName.c_str());
93         throw ast::ScilabError(szError, 999, *new Location());
94     }
95
96
97     ParserSingleInstance::disableStrictMode();
98     //  Parser::getInstance()->enableStrictMode();
99     ParserSingleInstance::setFileName(fileName);
100     ParserSingleInstance::setProgName(progName);
101
102     ParserSingleInstance::setExitStatus(Parser::Succeded);
103     ParserSingleInstance::resetControlStatus();
104     ParserSingleInstance::resetErrorMessage();
105     yyparse();
106     fclose(yyin);
107 }
108
109 void Parser::parse(char *command)
110 {
111     // Calling Parse state machine in C with global values
112     // Must be locked to avoid concurrent access
113     // FIXME : LOCK
114     if (getParseTrace() == true)
115     {
116         ParserSingleInstance::enableParseTrace();
117     }
118     else
119     {
120         ParserSingleInstance::disableParseTrace();
121     }
122
123     ParserSingleInstance::parse(command);
124     this->setExitStatus(ParserSingleInstance::getExitStatus());
125     this->setControlStatus(ParserSingleInstance::getControlStatus());
126     if (getExitStatus() == Parser::Succeded)
127     {
128         this->setTree(ParserSingleInstance::getTree());
129     }
130     else
131     {
132         this->setErrorMessage(ParserSingleInstance::getErrorMessage());
133     }
134
135     if (getControlStatus() == AllControlClosed && get_last_token() != YYEOF)
136     {
137         //set parser last token to EOF
138         scan_throw(YYEOF);
139     }
140
141     // FIXME : UNLOCK
142 }
143
144 void Parser::parse(wchar_t *command)
145 {
146     char* pstCommand = wide_string_to_UTF8(command);
147     parse(pstCommand);
148     FREE(pstCommand);
149 }
150
151 /** \brief parse the given file command */
152 void ParserSingleInstance::parse(char *command)
153 {
154     size_t len = strlen(command);
155
156     yylloc.first_line = yylloc.last_line = 1;
157     yylloc.first_column = yylloc.last_column = 1;
158 #ifdef _MSC_VER
159     char szFile[MAX_PATH];
160     char* pstTmpDIr = getTMPDIR();
161     os_sprintf(szFile, "%s\\%s", pstTmpDIr, "command.temp");
162     FREE(pstTmpDIr);
163     if (fileLocker)
164     {
165         fclose(fileLocker);
166     }
167
168     errno_t err;
169     err = fopen_s(&yyin, szFile, "w");
170     if (err)
171     {
172         ParserSingleInstance::setExitStatus(Parser::Failed);
173         ParserSingleInstance::resetErrorMessage();
174         wchar_t szError[bsiz];
175         wchar_t* wszFile = to_wide_string(szFile);
176         os_swprintf(szError, bsiz, _W("%ls: Cannot open file %ls.\n").c_str(), L"parser", wszFile);
177         FREE(wszFile);
178         appendErrorMessage(szError);
179         return;
180     }
181
182     fwrite(command, sizeof(char), len, yyin);
183     fclose(yyin);
184     fopen_s(&yyin, szFile, "r");
185 #endif
186
187 #ifdef __APPLE__
188     char szFile[PATH_MAX];
189     char* pstTmpDIr = "/tmp";
190     sprintf(szFile, "%s/%s", getTMPDIR(), "command.temp");
191     //FREE(pstTmpDIr);
192     if (fileLocker)
193     {
194         fclose(fileLocker);
195     }
196     yyin = fopen(szFile, "w");
197     fwrite(command, 1, len, yyin);
198     fclose(yyin);
199     yyin = fopen(szFile, "r");
200 #endif
201
202
203 #ifndef _MSC_VER
204 #ifndef __APPLE__
205     yyin = fmemopen(command, len, "r");
206 #endif
207 #endif
208
209     ParserSingleInstance::disableStrictMode();
210     ParserSingleInstance::setFileName(L"prompt");
211     ParserSingleInstance::setExitStatus(Parser::Succeded);
212     ParserSingleInstance::resetControlStatus();
213     ParserSingleInstance::resetErrorMessage();
214
215     yyparse();
216
217     fclose(yyin);
218 #ifdef _MSC_VER
219     DeleteFileA(szFile);
220 #endif
221
222 #ifdef _MSC_VER
223     //reopen a file to prevents max file opened.
224     fopen_s(&fileLocker, szFile, "w");
225 #endif
226 #ifdef __APPLE__
227     fileLocker = fopen(szFile, "w");
228 #endif
229 }
230
231 /** \brief put the asked line in codeLine */
232 char *ParserSingleInstance::getCodeLine(int line, char **codeLine)
233 {
234     int i = 0;
235
236     rewind(yyin);
237     /*
238     ** WARNING : *codeLine will be allocated by getline
239     ** so it must be manually freed !
240     */
241     for (i = 1 ; i <= line ; ++i)
242     {
243         fgets(*codeLine, 4096, yyin);
244     }
245     return *codeLine;
246 }
247
248 std::wstring& ParserSingleInstance::getErrorMessage(void)
249 {
250     return _error_message;
251 }
252
253 void ParserSingleInstance::appendErrorMessage(std::wstring message)
254 {
255     _error_message += message;
256 }
257
258 /** \brief enable Bison trace mode */
259 void ParserSingleInstance::enableParseTrace(void)
260 {
261     yydebug = 1;
262 }
263
264 /** \brief disable Bison trace mode */
265 void ParserSingleInstance::disableParseTrace(void)
266 {
267     yydebug = 0;
268 }
269
270 std::wstring ParserSingleInstance::_file_name;
271 std::wstring ParserSingleInstance::_prog_name;
272 std::wstring ParserSingleInstance::_error_message;
273 bool ParserSingleInstance::_strict_mode = false;
274 bool ParserSingleInstance::_stop_on_first_error = false;
275 ast::Exp* ParserSingleInstance::_the_program = NULL;
276 Parser::ParserStatus ParserSingleInstance::_exit_status = Parser::Succeded;
277 std::list<Parser::ControlStatus> ParserSingleInstance::_control_status;
278 FILE* ParserSingleInstance::fileLocker = NULL;
279