Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <idlc/idlc.hxx>
21 : #include <rtl/ustring.hxx>
22 : #include <rtl/strbuf.hxx>
23 : #include <osl/process.h>
24 : #include <osl/diagnose.h>
25 : #include <osl/thread.h>
26 : #include <osl/file.hxx>
27 :
28 : #if defined(SAL_W32)
29 : #include <io.h>
30 : #endif
31 :
32 : #ifdef SAL_UNX
33 : #include <errno.h>
34 : #include <unistd.h>
35 : #if defined(MACOSX) || defined(FREEBSD) || defined(NETBSD) || \
36 : defined(AIX) || defined(OPENBSD) || defined(DRAGONFLY)
37 : #include <sys/wait.h>
38 : #else
39 : #include <wait.h>
40 : #endif
41 : #endif
42 :
43 : #include <string.h>
44 :
45 : using namespace ::rtl;
46 : using namespace ::osl;
47 :
48 : extern int yyparse();
49 : extern FILE* yyin;
50 : extern int yydebug;
51 :
52 : sal_Int32 lineNumber = 1;
53 :
54 :
55 452 : static OUString TMP("TMP");
56 452 : static OUString TEMP("TEMP");
57 : static sal_Char tmpFilePattern[512];
58 :
59 43212 : sal_Bool isFileUrl(const OString& fileName)
60 : {
61 43212 : if (fileName.indexOf("file://") == 0 )
62 16145 : return sal_True;
63 27067 : return sal_False;
64 : }
65 :
66 26895 : OString convertToAbsoluteSystemPath(const OString& fileName)
67 : {
68 26895 : OUString uSysFileName;
69 53790 : OUString uFileName(fileName.getStr(), fileName.getLength(), osl_getThreadTextEncoding());
70 26895 : if ( isFileUrl(fileName) )
71 : {
72 10717 : if (FileBase::getSystemPathFromFileURL(uFileName, uSysFileName)
73 : != FileBase::E_None)
74 : {
75 : OSL_ASSERT(false);
76 : }
77 : } else
78 : {
79 32356 : OUString uWorkingDir, uUrlFileName, uTmp;
80 16178 : if (osl_getProcessWorkingDir(&uWorkingDir.pData) != osl_Process_E_None)
81 : {
82 : OSL_ASSERT(false);
83 : }
84 16178 : if (FileBase::getFileURLFromSystemPath(uFileName, uTmp)
85 : != FileBase::E_None)
86 : {
87 : OSL_ASSERT(false);
88 : }
89 16178 : if (FileBase::getAbsoluteFileURL(uWorkingDir, uTmp, uUrlFileName)
90 : != FileBase::E_None)
91 : {
92 : OSL_ASSERT(false);
93 : }
94 16178 : if (FileBase::getSystemPathFromFileURL(uUrlFileName, uSysFileName)
95 : != FileBase::E_None)
96 : {
97 : OSL_ASSERT(false);
98 16178 : }
99 : }
100 :
101 53790 : return OUStringToOString(uSysFileName, osl_getThreadTextEncoding());
102 : }
103 :
104 16317 : OString convertToFileUrl(const OString& fileName)
105 : {
106 16317 : if ( !isFileUrl(fileName) )
107 : {
108 10889 : OString tmp = convertToAbsoluteSystemPath(fileName);
109 21778 : OUString uFileName(tmp.getStr(), tmp.getLength(), osl_getThreadTextEncoding());
110 21778 : OUString uUrlFileName;
111 10889 : if (FileBase::getFileURLFromSystemPath(uFileName, uUrlFileName)
112 : != FileBase::E_None)
113 : {
114 : OSL_ASSERT(false);
115 : }
116 21778 : return OUStringToOString(uUrlFileName, osl_getThreadTextEncoding());
117 : }
118 :
119 5428 : return fileName;
120 : }
121 :
122 11200 : OString makeTempName(const OString& prefix)
123 : {
124 11200 : OUString uTmpPath;
125 22400 : OString tmpPath;
126 :
127 11200 : if ( osl_getEnvironment(TMP.pData, &uTmpPath.pData) != osl_Process_E_None )
128 : {
129 11200 : if ( osl_getEnvironment(TEMP.pData, &uTmpPath.pData) != osl_Process_E_None )
130 : {
131 : #if defined(SAL_W32)
132 : tmpPath = OString("c:\\temp");
133 : #else
134 11200 : tmpPath = OString("/tmp");
135 : #endif
136 : }
137 : }
138 :
139 11200 : if ( !uTmpPath.isEmpty() )
140 0 : tmpPath = OUStringToOString(uTmpPath, RTL_TEXTENCODING_UTF8);
141 :
142 : #if defined(SAL_W32) || defined(SAL_UNX)
143 :
144 : OSL_ASSERT( sizeof(tmpFilePattern) >
145 : (size_t) ( tmpPath.getLength()
146 : + RTL_CONSTASCII_LENGTH( PATH_SEPARATOR )
147 : + prefix.getLength()
148 : + RTL_CONSTASCII_LENGTH( "XXXXXX") ) );
149 :
150 11200 : tmpFilePattern[ sizeof(tmpFilePattern)-1 ] = '\0';
151 11200 : strncpy(tmpFilePattern, tmpPath.getStr(), sizeof(tmpFilePattern)-1);
152 11200 : strncat(tmpFilePattern, PATH_SEPARATOR, sizeof(tmpFilePattern)-1-strlen(tmpFilePattern));
153 11200 : strncat(tmpFilePattern, prefix.getStr(), sizeof(tmpFilePattern)-1-strlen(tmpFilePattern));
154 11200 : strncat(tmpFilePattern, "XXXXXX", sizeof(tmpFilePattern)-1-strlen(tmpFilePattern));
155 :
156 : #ifdef SAL_UNX
157 11200 : int nDescriptor = mkstemp(tmpFilePattern);
158 11200 : if( -1 == nDescriptor )
159 : {
160 0 : fprintf(stderr, "idlc: mkstemp(\"%s\") failed: %s\n", tmpFilePattern, strerror(errno));
161 0 : exit( 1 );
162 : }
163 : // the file shall later be reopened by stdio functions
164 11200 : close( nDescriptor );
165 : #else
166 : (void) mktemp(tmpFilePattern);
167 : #endif
168 : #endif
169 :
170 22400 : return OString(tmpFilePattern);
171 : }
172 :
173 5600 : sal_Bool copyFile(const OString* source, const OString& target)
174 : {
175 5600 : sal_Bool bRet = sal_True;
176 :
177 5600 : FILE* pSource = source == 0 ? stdin : fopen(source->getStr(), "rb");
178 5600 : if ( !pSource )
179 0 : return sal_False;
180 :
181 5600 : FILE* pTarget = fopen(target.getStr(), "wb");
182 5600 : if ( !pTarget )
183 : {
184 0 : fclose(pSource);
185 0 : return sal_False;
186 : }
187 :
188 5600 : size_t totalSize = 512;
189 5600 : size_t readSize = 0;
190 : char pBuffer[513];
191 :
192 39036 : while ( !feof(pSource) )
193 : {
194 27836 : if ( (readSize = fread(pBuffer, 1, totalSize, pSource)) > 0 && !ferror(pSource) )
195 : {
196 27823 : if ( (fwrite(pBuffer, 1, readSize, pTarget)) != readSize || ferror(pTarget) )
197 : {
198 0 : if (source != 0) {
199 0 : fclose(pSource);
200 : }
201 0 : fclose(pTarget);
202 0 : return sal_False;
203 : }
204 : }
205 : }
206 :
207 5600 : if (source != 0) {
208 5289 : fclose(pSource);
209 : }
210 5600 : if ( fflush(pTarget) )
211 0 : bRet = sal_False;
212 5600 : fclose(pTarget);
213 :
214 5600 : return bRet;
215 : }
216 :
217 5600 : sal_Int32 compileFile(const OString * pathname)
218 : {
219 : // preprocess input file
220 5600 : OString tmpFile = makeTempName(OString("idli_"));
221 11200 : OString preprocFile = makeTempName(OString("idlf_"));
222 :
223 11200 : OString fileName;
224 5600 : if (pathname == 0) {
225 311 : fileName = "stdin";
226 : } else {
227 5289 : fileName = *pathname;
228 : }
229 :
230 5600 : if ( !copyFile(pathname, tmpFile) )
231 : {
232 : fprintf(stderr, "%s: could not copy %s%s to %s\n",
233 0 : idlc()->getOptions()->getProgramName().getStr(),
234 : pathname == 0 ? "" : "file ", fileName.getStr(),
235 0 : tmpFile.getStr());
236 0 : exit(99);
237 : }
238 :
239 5600 : idlc()->setFileName(fileName);
240 5600 : idlc()->setMainFileName(fileName);
241 5600 : idlc()->setRealFileName(tmpFile);
242 :
243 11200 : ::std::vector< OUString> lCppArgs;
244 5600 : lCppArgs.push_back("-DIDL");
245 5600 : lCppArgs.push_back("-C");
246 5600 : lCppArgs.push_back("-zI");
247 :
248 11200 : OStringBuffer cppArgs(256);
249 5600 : Options* pOptions = idlc()->getOptions();
250 :
251 11200 : OString filePath;
252 5600 : sal_Int32 index = fileName.lastIndexOf(SEPARATOR);
253 :
254 5600 : if ( index > 0)
255 : {
256 5289 : filePath = fileName.copy(0, index);
257 :
258 5289 : if ( !filePath.isEmpty() )
259 : {
260 5289 : cppArgs.append("-I");
261 5289 : cppArgs.append(filePath);
262 : lCppArgs.push_back(OStringToOUString(
263 : cppArgs.makeStringAndClear().replace('\\', '/'),
264 5289 : RTL_TEXTENCODING_UTF8));
265 : }
266 : }
267 :
268 5600 : if ( pOptions->isValid("-D") )
269 : {
270 0 : OString token, dOpt = pOptions->getOption("-D");
271 0 : sal_Int32 nIndex = 0;
272 0 : do
273 : {
274 0 : token = dOpt.getToken( 0, ' ', nIndex );
275 0 : if (token.getLength())
276 0 : lCppArgs.push_back(OStringToOUString("-D" + token, RTL_TEXTENCODING_UTF8));
277 0 : } while( nIndex != -1 );
278 : }
279 :
280 5600 : if ( pOptions->isValid("-I") )
281 : {
282 10578 : OString token, incOpt = pOptions->getOption("-I");
283 5289 : sal_Int32 nIndex = 0;
284 11201 : do
285 : {
286 11201 : token = incOpt.getToken( 0, ' ', nIndex );
287 11201 : if (token.getLength())
288 11201 : lCppArgs.push_back(OStringToOUString("-I" + token, RTL_TEXTENCODING_UTF8));
289 16490 : } while( nIndex != -1 );
290 : }
291 :
292 5600 : lCppArgs.push_back(OUString("-o"));
293 :
294 5600 : cppArgs.append(preprocFile);
295 5600 : lCppArgs.push_back(OStringToOUString(cppArgs.makeStringAndClear(), RTL_TEXTENCODING_UTF8));
296 :
297 5600 : cppArgs.append(tmpFile);
298 5600 : lCppArgs.push_back(OStringToOUString(cppArgs.makeStringAndClear(), RTL_TEXTENCODING_UTF8));
299 :
300 11200 : OUString cpp;
301 11200 : OUString startDir;
302 : #ifndef SYSTEM_UCPP
303 5600 : if (osl_getExecutableFile(&cpp.pData) != osl_Process_E_None) {
304 : OSL_ASSERT(false);
305 : }
306 :
307 5600 : sal_Int32 idx= cpp.lastIndexOf("idlc");
308 5600 : cpp = cpp.copy(0, idx);
309 :
310 : #if defined(SAL_W32)
311 : cpp += "ucpp.exe";
312 : #else
313 5600 : cpp += "ucpp";
314 : #endif
315 : #else // SYSTEM_UCPP
316 : cpp = OUString( RTL_CONSTASCII_USTRINGPARAM(UCPP));
317 : #endif
318 5600 : oslProcess hProcess = NULL;
319 5600 : oslProcessError procError = osl_Process_E_None;
320 :
321 5600 : const int nCmdArgs = lCppArgs.size();
322 5600 : rtl_uString** pCmdArgs = 0;
323 5600 : pCmdArgs = (rtl_uString**)rtl_allocateZeroMemory(nCmdArgs * sizeof(rtl_uString*));
324 :
325 5600 : ::std::vector< OUString >::iterator iter = lCppArgs.begin();
326 5600 : ::std::vector< OUString >::iterator end = lCppArgs.end();
327 5600 : int i = 0;
328 61290 : while ( iter != end ) {
329 50090 : pCmdArgs[i++] = (*iter).pData;
330 50090 : ++iter;
331 : }
332 :
333 : procError = osl_executeProcess( cpp.pData, pCmdArgs, nCmdArgs, osl_Process_WAIT,
334 5600 : 0, startDir.pData, 0, 0, &hProcess );
335 :
336 : oslProcessInfo hInfo;
337 5600 : hInfo.Size = (sal_uInt32)(sizeof(oslProcessInfo));
338 5600 : if (osl_getProcessInfo(hProcess, osl_Process_EXITCODE, &hInfo)
339 : != osl_Process_E_None)
340 : {
341 : OSL_ASSERT(false);
342 : }
343 :
344 5600 : if ( procError || (hInfo.Code != 0) )
345 : {
346 0 : if ( procError != osl_Process_E_None )
347 0 : fprintf(stderr, "%s: starting preprocessor failed\n", pOptions->getProgramName().getStr());
348 : else
349 : fprintf(stderr, "%s: preprocessing %s%s failed\n",
350 0 : pOptions->getProgramName().getStr(),
351 0 : pathname == 0 ? "" : "file ", fileName.getStr());
352 :
353 0 : osl_freeProcessHandle(hProcess);
354 0 : rtl_freeMemory(pCmdArgs);
355 0 : exit(hInfo.Code ? hInfo.Code : 99);
356 : }
357 5600 : osl_freeProcessHandle(hProcess);
358 5600 : rtl_freeMemory(pCmdArgs);
359 :
360 5600 : if (unlink(tmpFile.getStr()) != 0)
361 : {
362 : fprintf(stderr, "%s: Could not remove cpp input file %s\n",
363 0 : pOptions->getProgramName().getStr(), tmpFile.getStr());
364 0 : exit(99);
365 : }
366 :
367 5600 : if ( pOptions->isValid("-E") )
368 : {
369 0 : if (unlink(preprocFile.getStr()) != 0)
370 : {
371 : fprintf(stderr, "%s: Could not remove parser input file %s\n",
372 0 : pOptions->getProgramName().getStr(), preprocFile.getStr());
373 0 : exit(99);
374 : }
375 0 : exit(0);
376 : }
377 :
378 : // parse file
379 5600 : yyin = fopen(preprocFile.getStr(), "r");
380 5600 : if (yyin == NULL)
381 : {
382 : fprintf(stderr, "%s: Could not open cpp output file %s\n",
383 0 : pOptions->getProgramName().getStr(), preprocFile.getStr());
384 0 : exit(99);
385 : }
386 :
387 : //yydebug = 0 no trace information
388 : //yydebug = 1 parser produce trace information
389 5600 : yydebug = 0;
390 :
391 5600 : sal_Int32 nErrors = yyparse();
392 5600 : nErrors = idlc()->getErrorCount();
393 :
394 5600 : fclose(yyin);
395 5600 : if (unlink(preprocFile.getStr()) != 0)
396 : {
397 : fprintf(stderr, "%s: Could not remove parser input file %s\n",
398 0 : pOptions->getProgramName().getStr(), preprocFile.getStr());
399 0 : exit(99);
400 : }
401 :
402 11200 : return nErrors;
403 1356 : }
404 :
405 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|