1ace2e3374dd7e4ac0f8b92c2a49d54bc4d4c646
[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(wchar_t *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     char* pstCommand = wide_string_to_UTF8(command);
124     ParserSingleInstance::parse(pstCommand);
125     this->setExitStatus(ParserSingleInstance::getExitStatus());
126     this->setControlStatus(ParserSingleInstance::getControlStatus());
127     if (getExitStatus() == Parser::Succeded)
128     {
129         this->setTree(ParserSingleInstance::getTree());
130     }
131     else
132     {
133         this->setErrorMessage(ParserSingleInstance::getErrorMessage());
134     }
135
136     if (getControlStatus() == AllControlClosed && get_last_token() != YYEOF)
137     {
138         //set parser last token to EOF
139         scan_throw(YYEOF);
140     }
141
142     FREE(pstCommand);
143     // FIXME : UNLOCK
144 }
145
146 /** \brief parse the given file command */
147 void ParserSingleInstance::parse(char *command)
148 {
149     size_t len = strlen(command);
150
151     yylloc.first_line = yylloc.last_line = 1;
152     yylloc.first_column = yylloc.last_column = 1;
153 #ifdef _MSC_VER
154     char szFile[MAX_PATH];
155     char* pstTmpDIr = getTMPDIR();
156     os_sprintf(szFile, "%s\\%s", pstTmpDIr, "command.temp");
157     FREE(pstTmpDIr);
158     if (fileLocker)
159     {
160         fclose(fileLocker);
161     }
162
163     fopen_s(&yyin, szFile, "w");
164     fwrite(command, sizeof(char), len, yyin);
165     fclose(yyin);
166     fopen_s(&yyin, szFile, "r");
167 #endif
168
169 #ifdef __APPLE__
170     char szFile[PATH_MAX];
171     char* pstTmpDIr = "/tmp";
172     sprintf(szFile, "%s/%s", getTMPDIR(), "command.temp");
173     //FREE(pstTmpDIr);
174     if (fileLocker)
175     {
176         fclose(fileLocker);
177     }
178     yyin = fopen(szFile, "w");
179     fwrite(command, 1, len, yyin);
180     fclose(yyin);
181     yyin = fopen(szFile, "r");
182 #endif
183
184
185 #ifndef _MSC_VER
186 #ifndef __APPLE__
187     yyin = fmemopen(command, len, "r");
188 #endif
189 #endif
190
191     ParserSingleInstance::disableStrictMode();
192     ParserSingleInstance::setFileName(L"prompt");
193     ParserSingleInstance::setExitStatus(Parser::Succeded);
194     ParserSingleInstance::resetControlStatus();
195     ParserSingleInstance::resetErrorMessage();
196
197     yyparse();
198
199     fclose(yyin);
200 #ifdef _MSC_VER
201     DeleteFileA(szFile);
202 #endif
203
204 #ifdef _MSC_VER
205     //reopen a file to prevents max file opened.
206     fopen_s(&fileLocker, szFile, "w");
207 #endif
208 #ifdef __APPLE__
209     fileLocker = fopen(szFile, "w");
210 #endif
211 }
212
213 /** \brief put the asked line in codeLine */
214 char *ParserSingleInstance::getCodeLine(int line, char **codeLine)
215 {
216     int i = 0;
217
218     rewind(yyin);
219     /*
220     ** WARNING : *codeLine will be allocated by getline
221     ** so it must be manually freed !
222     */
223     for (i = 1 ; i <= line ; ++i)
224     {
225         fgets(*codeLine, 4096, yyin);
226     }
227     return *codeLine;
228 }
229
230 std::wstring& ParserSingleInstance::getErrorMessage(void)
231 {
232     return _error_message;
233 }
234
235 void ParserSingleInstance::appendErrorMessage(std::wstring message)
236 {
237     _error_message += message;
238 }
239
240 /** \brief enable Bison trace mode */
241 void ParserSingleInstance::enableParseTrace(void)
242 {
243     yydebug = 1;
244 }
245
246 /** \brief disable Bison trace mode */
247 void ParserSingleInstance::disableParseTrace(void)
248 {
249     yydebug = 0;
250 }
251
252 std::wstring ParserSingleInstance::_file_name;
253 std::wstring ParserSingleInstance::_prog_name;
254 std::wstring ParserSingleInstance::_error_message;
255 bool ParserSingleInstance::_strict_mode = false;
256 bool ParserSingleInstance::_stop_on_first_error = false;
257 ast::Exp* ParserSingleInstance::_the_program = NULL;
258 Parser::ParserStatus ParserSingleInstance::_exit_status = Parser::Succeded;
259 std::list<Parser::ControlStatus> ParserSingleInstance::_control_status;
260 FILE* ParserSingleInstance::fileLocker = NULL;
261