4864358287b3438d14ac22a28fb0b43157496940
[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_swprintf.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
42 void Parser::parseFile(const std::wstring& fileName, const std::wstring& progName)
43 {
44     // Calling Parse state machine in C with global values
45     // Must be locked to avoid concurrent access
46     // FIXME : LOCK
47     if (getParseTrace() == true)
48     {
49         ParserSingleInstance::enableParseTrace();
50     }
51     else
52     {
53         ParserSingleInstance::disableParseTrace();
54     }
55     ParserSingleInstance::parseFile(fileName, progName);
56     this->setExitStatus(ParserSingleInstance::getExitStatus());
57     this->setControlStatus(ParserSingleInstance::getControlStatus());
58     if (getExitStatus() == Parser::Succeded)
59     {
60         this->setTree(ParserSingleInstance::getTree());
61     }
62     else
63     {
64         this->setErrorMessage(ParserSingleInstance::getErrorMessage());
65     }
66     // FIXME : UNLOCK
67 }
68
69
70 /** \brief parse the given file name */
71 void ParserSingleInstance::parseFile(const std::wstring& fileName, const std::wstring& progName)
72 {
73     yylloc.first_line = yylloc.last_line = 1;
74     yylloc.first_column = yylloc.last_column = 1;
75 #ifdef _MSC_VER
76     _wfopen_s(&yyin, fileName.c_str(), L"r");
77 #else
78     char* pstTemp = wide_string_to_UTF8(fileName.c_str());
79     yyin = fopen(pstTemp, "r");
80     FREE(pstTemp);
81 #endif
82
83     if (!yyin)
84     {
85         wchar_t szError[bsiz];
86         os_swprintf(szError, bsiz, _W("%ls: Cannot open file %ls.\n").c_str(), L"parser", fileName.c_str());
87         throw ast::ScilabError(szError, 999, *new Location());
88     }
89
90
91     ParserSingleInstance::disableStrictMode();
92     //  Parser::getInstance()->enableStrictMode();
93     ParserSingleInstance::setFileName(fileName);
94     ParserSingleInstance::setProgName(progName);
95
96     ParserSingleInstance::setExitStatus(Parser::Succeded);
97     ParserSingleInstance::resetControlStatus();
98     ParserSingleInstance::resetErrorMessage();
99     yyparse();
100     fclose(yyin);
101 }
102
103 void Parser::parse(wchar_t *command)
104 {
105     // Calling Parse state machine in C with global values
106     // Must be locked to avoid concurrent access
107     // FIXME : LOCK
108     if (getParseTrace() == true)
109     {
110         ParserSingleInstance::enableParseTrace();
111     }
112     else
113     {
114         ParserSingleInstance::disableParseTrace();
115     }
116
117     char* pstCommand = wide_string_to_UTF8(command);
118     ParserSingleInstance::parse(pstCommand);
119     this->setExitStatus(ParserSingleInstance::getExitStatus());
120     this->setControlStatus(ParserSingleInstance::getControlStatus());
121     if (getExitStatus() == Parser::Succeded)
122     {
123         this->setTree(ParserSingleInstance::getTree());
124     }
125     else
126     {
127         this->setErrorMessage(ParserSingleInstance::getErrorMessage());
128     }
129
130     if (getControlStatus() == AllControlClosed && get_last_token() != YYEOF)
131     {
132         //set parser last token to EOF
133         scan_throw(YYEOF);
134     }
135
136     FREE(pstCommand);
137     // FIXME : UNLOCK
138 }
139
140 /** \brief parse the given file command */
141 void ParserSingleInstance::parse(char *command)
142 {
143     size_t len = strlen(command);
144
145     yylloc.first_line = yylloc.last_line = 1;
146     yylloc.first_column = yylloc.last_column = 1;
147 #ifdef _MSC_VER
148     char szFile[MAX_PATH];
149     char* pstTmpDIr = getTMPDIR();
150     sprintf(szFile, "%s\\%s", pstTmpDIr, "command.temp");
151     FREE(pstTmpDIr);
152     if (fileLocker)
153     {
154         fclose(fileLocker);
155     }
156
157     fopen_s(&yyin, szFile, "w");
158     fwrite(command, sizeof(char), len, yyin);
159     fclose(yyin);
160     fopen_s(&yyin, szFile, "r");
161 #endif
162
163 #ifdef __APPLE__
164     char szFile[PATH_MAX];
165     char* pstTmpDIr = "/tmp";
166     sprintf(szFile, "%s/%s", getTMPDIR(), "command.temp");
167     //FREE(pstTmpDIr);
168     if (fileLocker)
169     {
170         fclose(fileLocker);
171     }
172     yyin = fopen(szFile, "w");
173     fwrite(command, 1, len, yyin);
174     fclose(yyin);
175     yyin = fopen(szFile, "r");
176 #endif
177
178
179 #ifndef _MSC_VER
180 #ifndef __APPLE__
181     yyin = fmemopen(command, len, "r");
182 #endif
183 #endif
184
185     ParserSingleInstance::disableStrictMode();
186     ParserSingleInstance::setFileName(L"prompt");
187     ParserSingleInstance::setExitStatus(Parser::Succeded);
188     ParserSingleInstance::resetControlStatus();
189     ParserSingleInstance::resetErrorMessage();
190
191     yyparse();
192
193     fclose(yyin);
194 #ifdef _MSC_VER
195     DeleteFileA(szFile);
196 #endif
197
198 #ifdef _MSC_VER
199     //reopen a file to prevents max file opened.
200     fopen_s(&fileLocker, szFile, "w");
201 #endif
202 #ifdef __APPLE__
203     fileLocker = fopen(szFile, "w");
204 #endif
205 }
206
207 /** \brief put the asked line in codeLine */
208 char *ParserSingleInstance::getCodeLine(int line, char **codeLine)
209 {
210     int i = 0;
211
212     rewind(yyin);
213     /*
214     ** WARNING : *codeLine will be allocated by getline
215     ** so it must be manually freed !
216     */
217     for (i = 1 ; i <= line ; ++i)
218     {
219         fgets(*codeLine, 4096, yyin);
220     }
221     return *codeLine;
222 }
223
224 std::wstring& ParserSingleInstance::getErrorMessage(void)
225 {
226     return _error_message;
227 }
228
229 void ParserSingleInstance::appendErrorMessage(std::wstring message)
230 {
231     _error_message += message;
232 }
233
234 /** \brief enable Bison trace mode */
235 void ParserSingleInstance::enableParseTrace(void)
236 {
237     yydebug = 1;
238 }
239
240 /** \brief disable Bison trace mode */
241 void ParserSingleInstance::disableParseTrace(void)
242 {
243     yydebug = 0;
244 }
245
246 std::wstring ParserSingleInstance::_file_name;
247 std::wstring ParserSingleInstance::_prog_name;
248 std::wstring ParserSingleInstance::_error_message;
249 bool ParserSingleInstance::_strict_mode = false;
250 bool ParserSingleInstance::_stop_on_first_error = false;
251 ast::Exp* ParserSingleInstance::_the_program = NULL;
252 Parser::ParserStatus ParserSingleInstance::_exit_status = Parser::Succeded;
253 std::list<Parser::ControlStatus> ParserSingleInstance::_control_status;
254 FILE* ParserSingleInstance::fileLocker = NULL;
255