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 ::osl;
46 :
47 : extern int yyparse();
48 : extern FILE* yyin;
49 : extern int yydebug;
50 :
51 : sal_Int32 lineNumber = 1;
52 :
53 :
54 : static const char TMP[] = "TMP";
55 : static const char TEMP[] = "TEMP";
56 : static sal_Char tmpFilePattern[512];
57 :
58 1275 : bool isFileUrl(const OString& fileName)
59 : {
60 1275 : if (fileName.startsWith("file://") )
61 288 : return true;
62 987 : return false;
63 : }
64 :
65 802 : OString convertToAbsoluteSystemPath(const OString& fileName)
66 : {
67 802 : OUString uSysFileName;
68 1604 : OUString uFileName(fileName.getStr(), fileName.getLength(), osl_getThreadTextEncoding());
69 802 : if ( isFileUrl(fileName) )
70 : {
71 144 : if (FileBase::getSystemPathFromFileURL(uFileName, uSysFileName)
72 : != FileBase::E_None)
73 : {
74 : OSL_ASSERT(false);
75 : }
76 : } else
77 : {
78 1316 : OUString uWorkingDir, uUrlFileName, uTmp;
79 658 : if (osl_getProcessWorkingDir(&uWorkingDir.pData) != osl_Process_E_None)
80 : {
81 : OSL_ASSERT(false);
82 : }
83 658 : if (FileBase::getFileURLFromSystemPath(uFileName, uTmp)
84 : != FileBase::E_None)
85 : {
86 : OSL_ASSERT(false);
87 : }
88 658 : if (FileBase::getAbsoluteFileURL(uWorkingDir, uTmp, uUrlFileName)
89 : != FileBase::E_None)
90 : {
91 : OSL_ASSERT(false);
92 : }
93 658 : if (FileBase::getSystemPathFromFileURL(uUrlFileName, uSysFileName)
94 : != FileBase::E_None)
95 : {
96 : OSL_ASSERT(false);
97 658 : }
98 : }
99 :
100 1604 : return OUStringToOString(uSysFileName, osl_getThreadTextEncoding());
101 : }
102 :
103 473 : OString convertToFileUrl(const OString& fileName)
104 : {
105 473 : if ( !isFileUrl(fileName) )
106 : {
107 329 : OString tmp = convertToAbsoluteSystemPath(fileName);
108 658 : OUString uFileName(tmp.getStr(), tmp.getLength(), osl_getThreadTextEncoding());
109 658 : OUString uUrlFileName;
110 329 : if (FileBase::getFileURLFromSystemPath(uFileName, uUrlFileName)
111 : != FileBase::E_None)
112 : {
113 : OSL_ASSERT(false);
114 : }
115 658 : return OUStringToOString(uUrlFileName, osl_getThreadTextEncoding());
116 : }
117 :
118 144 : return fileName;
119 : }
120 :
121 658 : OString makeTempName(const OString& prefix)
122 : {
123 658 : OUString uTmpPath;
124 1316 : OString tmpPath;
125 :
126 658 : if ( osl_getEnvironment(OUString(TMP).pData, &uTmpPath.pData) != osl_Process_E_None )
127 : {
128 658 : if ( osl_getEnvironment(OUString(TEMP).pData, &uTmpPath.pData) != osl_Process_E_None )
129 : {
130 : #if defined(SAL_W32)
131 : tmpPath = OString("c:\\temp");
132 : #else
133 658 : tmpPath = OString("/tmp");
134 : #endif
135 : }
136 : }
137 :
138 658 : if ( !uTmpPath.isEmpty() )
139 0 : tmpPath = OUStringToOString(uTmpPath, RTL_TEXTENCODING_UTF8);
140 :
141 : #if defined(SAL_W32) || defined(SAL_UNX)
142 :
143 : OSL_ASSERT( sizeof(tmpFilePattern) >
144 : (size_t) ( tmpPath.getLength()
145 : + RTL_CONSTASCII_LENGTH( PATH_SEPARATOR )
146 : + prefix.getLength()
147 : + RTL_CONSTASCII_LENGTH( "XXXXXX") ) );
148 :
149 658 : tmpFilePattern[ sizeof(tmpFilePattern)-1 ] = '\0';
150 658 : strncpy(tmpFilePattern, tmpPath.getStr(), sizeof(tmpFilePattern)-1);
151 658 : strncat(tmpFilePattern, PATH_SEPARATOR, sizeof(tmpFilePattern)-1-strlen(tmpFilePattern));
152 658 : strncat(tmpFilePattern, prefix.getStr(), sizeof(tmpFilePattern)-1-strlen(tmpFilePattern));
153 658 : strncat(tmpFilePattern, "XXXXXX", sizeof(tmpFilePattern)-1-strlen(tmpFilePattern));
154 :
155 : #ifdef SAL_UNX
156 : // coverity[secure_temp] - https://communities.coverity.com/thread/3179
157 658 : int nDescriptor = mkstemp(tmpFilePattern);
158 658 : 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 658 : close( nDescriptor );
165 : #else
166 : (void) mktemp(tmpFilePattern);
167 : #endif
168 : #endif
169 :
170 1316 : return OString(tmpFilePattern);
171 : }
172 :
173 329 : bool copyFile(const OString* source, const OString& target)
174 : {
175 329 : bool bRet = true;
176 :
177 329 : FILE* pSource = source == 0 ? stdin : fopen(source->getStr(), "rb");
178 329 : if ( !pSource )
179 0 : return false;
180 :
181 329 : FILE* pTarget = fopen(target.getStr(), "wb");
182 329 : if ( !pTarget )
183 : {
184 0 : fclose(pSource);
185 0 : return false;
186 : }
187 :
188 329 : size_t totalSize = 512;
189 : char pBuffer[513];
190 :
191 989 : while ( !feof(pSource) )
192 : {
193 : size_t readSize;
194 331 : if ( (readSize = fread(pBuffer, 1, totalSize, pSource)) > 0 && !ferror(pSource) )
195 : {
196 331 : 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 false;
203 : }
204 : }
205 : }
206 :
207 329 : if (source != 0) {
208 329 : fclose(pSource);
209 : }
210 329 : if ( fflush(pTarget) )
211 0 : bRet = false;
212 329 : fclose(pTarget);
213 :
214 329 : return bRet;
215 : }
216 :
217 329 : sal_Int32 compileFile(const OString * pathname)
218 : {
219 : // preprocess input file
220 329 : OString tmpFile = makeTempName(OString("idli_"));
221 658 : OString preprocFile = makeTempName(OString("idlf_"));
222 :
223 658 : OString fileName;
224 329 : if (pathname == 0) {
225 0 : fileName = "stdin";
226 : } else {
227 329 : fileName = *pathname;
228 : }
229 :
230 329 : 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 329 : idlc()->setFileName(fileName);
240 329 : idlc()->setMainFileName(fileName);
241 329 : idlc()->setRealFileName(tmpFile);
242 :
243 658 : ::std::vector< OUString> lCppArgs;
244 329 : lCppArgs.push_back("-DIDL");
245 329 : lCppArgs.push_back("-C");
246 329 : lCppArgs.push_back("-zI");
247 :
248 658 : OStringBuffer cppArgs(256);
249 329 : Options* pOptions = idlc()->getOptions();
250 :
251 658 : OString filePath;
252 329 : sal_Int32 index = fileName.lastIndexOf(SEPARATOR);
253 :
254 329 : if ( index > 0)
255 : {
256 329 : filePath = fileName.copy(0, index);
257 :
258 329 : if ( !filePath.isEmpty() )
259 : {
260 329 : cppArgs.append("-I");
261 329 : cppArgs.append(filePath);
262 : lCppArgs.push_back(OStringToOUString(
263 : cppArgs.makeStringAndClear().replace('\\', '/'),
264 329 : RTL_TEXTENCODING_UTF8));
265 : }
266 : }
267 :
268 329 : 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 329 : if ( pOptions->isValid("-I") )
281 : {
282 0 : OString token, incOpt = pOptions->getOption("-I");
283 0 : sal_Int32 nIndex = 0;
284 0 : do
285 : {
286 0 : token = incOpt.getToken( 0, ' ', nIndex );
287 0 : if (token.getLength())
288 0 : lCppArgs.push_back(OStringToOUString("-I" + token, RTL_TEXTENCODING_UTF8));
289 0 : } while( nIndex != -1 );
290 : }
291 :
292 329 : lCppArgs.push_back(OUString("-o"));
293 :
294 329 : cppArgs.append(preprocFile);
295 329 : lCppArgs.push_back(OStringToOUString(cppArgs.makeStringAndClear(), RTL_TEXTENCODING_UTF8));
296 :
297 329 : cppArgs.append(tmpFile);
298 329 : lCppArgs.push_back(OStringToOUString(cppArgs.makeStringAndClear(), RTL_TEXTENCODING_UTF8));
299 :
300 658 : OUString cpp;
301 658 : OUString startDir;
302 : #ifndef SYSTEM_UCPP
303 329 : if (osl_getExecutableFile(&cpp.pData) != osl_Process_E_None) {
304 : OSL_ASSERT(false);
305 : }
306 :
307 329 : sal_Int32 idx= cpp.lastIndexOf("idlc");
308 329 : cpp = cpp.copy(0, idx);
309 :
310 : #if defined(SAL_W32)
311 : cpp += "ucpp.exe";
312 : #else
313 329 : cpp += "ucpp";
314 : #endif
315 : #else // SYSTEM_UCPP
316 : cpp = OUString(UCPP);
317 : #endif
318 329 : oslProcess hProcess = NULL;
319 329 : oslProcessError procError = osl_Process_E_None;
320 :
321 329 : const int nCmdArgs = lCppArgs.size();
322 329 : rtl_uString** pCmdArgs = 0;
323 329 : pCmdArgs = static_cast<rtl_uString**>(rtl_allocateZeroMemory(nCmdArgs * sizeof(rtl_uString*)));
324 :
325 329 : ::std::vector< OUString >::iterator iter = lCppArgs.begin();
326 329 : ::std::vector< OUString >::iterator end = lCppArgs.end();
327 329 : int i = 0;
328 2961 : while ( iter != end ) {
329 2303 : pCmdArgs[i++] = (*iter).pData;
330 2303 : ++iter;
331 : }
332 :
333 : procError = osl_executeProcess( cpp.pData, pCmdArgs, nCmdArgs, osl_Process_WAIT,
334 329 : 0, startDir.pData, 0, 0, &hProcess );
335 :
336 : oslProcessInfo hInfo;
337 329 : hInfo.Size = (sal_uInt32)(sizeof(oslProcessInfo));
338 329 : if (osl_getProcessInfo(hProcess, osl_Process_EXITCODE, &hInfo)
339 : != osl_Process_E_None)
340 : {
341 : OSL_ASSERT(false);
342 : }
343 :
344 329 : 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 329 : osl_freeProcessHandle(hProcess);
358 329 : rtl_freeMemory(pCmdArgs);
359 :
360 329 : 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 329 : 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 329 : yyin = fopen(preprocFile.getStr(), "r");
380 329 : 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 329 : yydebug = 0;
390 :
391 329 : sal_Int32 nErrors = yyparse();
392 329 : nErrors = idlc()->getErrorCount();
393 :
394 329 : fclose(yyin);
395 329 : 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 658 : return nErrors;
403 : }
404 :
405 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|