sc: copy cache values when clone color conditional format
[LibreOffice.git] / idlc / source / idlccompile.cxx
blob0d06ea59cdbee29ba0b49b3867b494f964ed0182
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <idlc.hxx>
21 #include <rtl/alloc.h>
22 #include <rtl/ustring.hxx>
23 #include <rtl/strbuf.hxx>
24 #include <o3tl/safeint.hxx>
25 #include <o3tl/string_view.hxx>
26 #include <osl/process.h>
27 #include <osl/diagnose.h>
28 #include <osl/thread.h>
29 #include <osl/file.hxx>
31 #if defined(_WIN32)
32 #include <io.h>
33 #endif
35 #ifdef SAL_UNX
36 #include <errno.h>
37 #include <unistd.h>
38 #include <sys/wait.h>
39 #endif
41 #include <string.h>
43 using namespace ::osl;
45 extern int yyparse();
46 extern FILE* yyin;
47 extern int yydebug;
49 static char tmpFilePattern[512];
51 bool isFileUrl(std::string_view fileName)
53 return o3tl::starts_with(fileName, "file://");
56 OString convertToAbsoluteSystemPath(const OString& fileName)
58 OUString uSysFileName;
59 OUString uFileName(fileName.getStr(), fileName.getLength(), osl_getThreadTextEncoding());
60 if ( isFileUrl(fileName) )
62 if (FileBase::getSystemPathFromFileURL(uFileName, uSysFileName)
63 != FileBase::E_None)
65 OSL_ASSERT(false);
67 } else
69 OUString uWorkingDir, uUrlFileName, uTmp;
70 if (osl_getProcessWorkingDir(&uWorkingDir.pData) != osl_Process_E_None)
72 OSL_ASSERT(false);
74 if (FileBase::getFileURLFromSystemPath(uFileName, uTmp)
75 != FileBase::E_None)
77 OSL_ASSERT(false);
79 if (FileBase::getAbsoluteFileURL(uWorkingDir, uTmp, uUrlFileName)
80 != FileBase::E_None)
82 OSL_ASSERT(false);
84 if (FileBase::getSystemPathFromFileURL(uUrlFileName, uSysFileName)
85 != FileBase::E_None)
87 OSL_ASSERT(false);
91 return OUStringToOString(uSysFileName, osl_getThreadTextEncoding());
94 OString convertToFileUrl(const OString& fileName)
96 if ( !isFileUrl(fileName) )
98 OString tmp = convertToAbsoluteSystemPath(fileName);
99 OUString uFileName(tmp.getStr(), tmp.getLength(), osl_getThreadTextEncoding());
100 OUString uUrlFileName;
101 if (FileBase::getFileURLFromSystemPath(uFileName, uUrlFileName)
102 != FileBase::E_None)
104 OSL_ASSERT(false);
106 return OUStringToOString(uUrlFileName, osl_getThreadTextEncoding());
109 return fileName;
112 static OString makeTempName(const OString& prefix)
114 OUString uTmpPath;
115 OString tmpPath;
117 if ( osl_getEnvironment(OUString("TMP").pData, &uTmpPath.pData) != osl_Process_E_None )
119 if ( osl_getEnvironment(OUString("TEMP").pData, &uTmpPath.pData) != osl_Process_E_None )
121 #if defined(_WIN32)
122 tmpPath = OString("c:\\temp");
123 #else
124 tmpPath = OString("/tmp");
125 #endif
129 if ( !uTmpPath.isEmpty() )
130 tmpPath = OUStringToOString(uTmpPath, RTL_TEXTENCODING_UTF8);
132 #if defined(_WIN32) || defined(SAL_UNX)
134 OSL_ASSERT( sizeof(tmpFilePattern) >
135 o3tl::make_unsigned( tmpPath.getLength()
136 + RTL_CONSTASCII_LENGTH( PATH_SEPARATOR )
137 + prefix.getLength()
138 + RTL_CONSTASCII_LENGTH( "XXXXXX") ) );
140 tmpFilePattern[ sizeof(tmpFilePattern)-1 ] = '\0';
141 strncpy(tmpFilePattern, tmpPath.getStr(), sizeof(tmpFilePattern)-1);
142 strncat(tmpFilePattern, PATH_SEPARATOR, sizeof(tmpFilePattern)-1-strlen(tmpFilePattern));
143 strncat(tmpFilePattern, prefix.getStr(), sizeof(tmpFilePattern)-1-strlen(tmpFilePattern));
144 strncat(tmpFilePattern, "XXXXXX", sizeof(tmpFilePattern)-1-strlen(tmpFilePattern));
146 #ifdef SAL_UNX
147 // coverity[secure_temp] - https://communities.coverity.com/thread/3179
148 int nDescriptor = mkstemp(tmpFilePattern);
149 if( -1 == nDescriptor )
151 fprintf(stderr, "idlc: mkstemp(\"%s\") failed: %s\n", tmpFilePattern, strerror(errno));
152 exit( 1 );
154 // the file shall later be reopened by stdio functions
155 close( nDescriptor );
156 #else
157 (void) mktemp(tmpFilePattern);
158 #endif
159 #endif
161 return tmpFilePattern;
164 bool copyFile(const OString* source, const OString& target)
166 bool bRet = true;
168 FILE* pSource = source == nullptr ? stdin : fopen(source->getStr(), "rb");
169 if ( !pSource )
170 return false;
172 FILE* pTarget = fopen(target.getStr(), "wb");
173 if ( !pTarget )
175 fclose(pSource);
176 return false;
179 size_t const totalSize = 512;
180 char pBuffer[totalSize + 1];
182 while ( !feof(pSource) )
184 size_t readSize = fread(pBuffer, 1, totalSize, pSource);
185 if ( readSize > 0 && !ferror(pSource) )
187 if ( (fwrite(pBuffer, 1, readSize, pTarget)) != readSize || ferror(pTarget) )
189 if (source != nullptr) {
190 fclose(pSource);
192 fclose(pTarget);
193 return false;
198 if (source != nullptr) {
199 fclose(pSource);
201 if ( fclose(pTarget) )
202 bRet = false;
204 return bRet;
207 sal_Int32 compileFile(const OString * pathname)
209 // preprocess input file
210 OString tmpFile = makeTempName("idli_");
211 OString preprocFile = makeTempName("idlf_");
213 OString fileName;
214 if (pathname == nullptr) {
215 fileName = "stdin";
216 } else {
217 fileName = *pathname;
220 if ( !copyFile(pathname, tmpFile) )
222 fprintf(stderr, "%s: could not copy %s%s to %s\n",
223 idlc()->getOptions()->getProgramName().getStr(),
224 pathname == nullptr ? "" : "file ", fileName.getStr(),
225 tmpFile.getStr());
226 exit(99);
229 idlc()->setFileName(fileName);
230 idlc()->setMainFileName(fileName);
231 idlc()->setRealFileName(tmpFile);
233 ::std::vector< OUString> lCppArgs;
234 lCppArgs.emplace_back("-DIDL");
235 lCppArgs.emplace_back("-C");
236 #ifdef SYSTEM_UCPP_IS_GCC
237 // -nostdinc Do not search the standard system directories for header files
238 lCppArgs.emplace_back("-nostdinc");
239 // with gcc cpp, even when not explicitly including anything, /usr/include/stdc-predef.h
240 // gets inserted without -nostdinc
241 #else
242 // -zI Do not use the standard (compile-time) include path.
243 lCppArgs.emplace_back("-zI");
244 #endif
246 Options* pOptions = idlc()->getOptions();
248 OString filePath;
249 sal_Int32 index = fileName.lastIndexOf(SEPARATOR);
251 if ( index > 0)
253 filePath = fileName.copy(0, index);
255 if ( !filePath.isEmpty() )
257 OString cppArgs = "-I" + filePath;
258 lCppArgs.push_back(OStringToOUString(
259 cppArgs.replace('\\', '/'),
260 RTL_TEXTENCODING_UTF8));
264 if ( pOptions->isValid("-D") )
266 OString token, dOpt = pOptions->getOption("-D");
267 sal_Int32 nIndex = 0;
270 token = dOpt.getToken( 0, ' ', nIndex );
271 if (token.getLength())
272 lCppArgs.push_back("-D" + OStringToOUString(token, RTL_TEXTENCODING_UTF8));
273 } while( nIndex != -1 );
276 if ( pOptions->isValid("-I") )
278 OString token, incOpt = pOptions->getOption("-I");
279 sal_Int32 nIndex = 0;
282 token = incOpt.getToken( 0, ' ', nIndex );
283 if (token.getLength())
284 lCppArgs.push_back("-I" + OStringToOUString(token, RTL_TEXTENCODING_UTF8));
285 } while( nIndex != -1 );
288 lCppArgs.emplace_back("-o");
290 lCppArgs.push_back(OStringToOUString(preprocFile, RTL_TEXTENCODING_UTF8));
292 lCppArgs.push_back(OStringToOUString(tmpFile, RTL_TEXTENCODING_UTF8));
294 OUString cpp;
295 OUString startDir;
296 #ifndef SYSTEM_UCPP
297 if (osl_getExecutableFile(&cpp.pData) != osl_Process_E_None) {
298 OSL_ASSERT(false);
301 sal_Int32 idx= cpp.lastIndexOf("idlc");
302 cpp = cpp.copy(0, idx);
304 #if defined(_WIN32)
305 cpp += "ucpp.exe";
306 #else
307 cpp += "ucpp";
308 #endif
309 #else // SYSTEM_UCPP
310 cpp = OUString(UCPP);
311 #endif
312 oslProcess hProcess = nullptr;
313 oslProcessError procError = osl_Process_E_None;
315 const int nCmdArgs = lCppArgs.size();
316 std::unique_ptr<rtl_uString*[]> pCmdArgs(new rtl_uString*[nCmdArgs]);
318 int i = 0;
319 for (auto const& elem : lCppArgs)
321 pCmdArgs[i++] = elem.pData;
324 procError = osl_executeProcess( cpp.pData, pCmdArgs.get(), nCmdArgs, osl_Process_WAIT,
325 nullptr, startDir.pData, nullptr, 0, &hProcess );
327 oslProcessInfo hInfo;
328 hInfo.Size = sal_uInt32(sizeof(oslProcessInfo));
329 if (osl_getProcessInfo(hProcess, osl_Process_EXITCODE, &hInfo)
330 != osl_Process_E_None)
332 OSL_ASSERT(false);
335 if ( procError || (hInfo.Code != 0) )
337 if ( procError != osl_Process_E_None )
338 fprintf(stderr, "%s: starting preprocessor failed\n", pOptions->getProgramName().getStr());
339 else
340 fprintf(stderr, "%s: preprocessing %s%s failed\n",
341 pOptions->getProgramName().getStr(),
342 pathname == nullptr ? "" : "file ", fileName.getStr());
344 osl_freeProcessHandle(hProcess);
345 exit(hInfo.Code ? hInfo.Code : 99);
347 osl_freeProcessHandle(hProcess);
349 if (unlink(tmpFile.getStr()) != 0)
351 fprintf(stderr, "%s: Could not remove cpp input file %s\n",
352 pOptions->getProgramName().getStr(), tmpFile.getStr());
353 exit(99);
356 if ( pOptions->isValid("-E") )
358 if (unlink(preprocFile.getStr()) != 0)
360 fprintf(stderr, "%s: Could not remove parser input file %s\n",
361 pOptions->getProgramName().getStr(), preprocFile.getStr());
362 exit(99);
364 exit(0);
367 // parse file
368 yyin = fopen(preprocFile.getStr(), "r");
369 if (yyin == nullptr)
371 fprintf(stderr, "%s: Could not open cpp output file %s\n",
372 pOptions->getProgramName().getStr(), preprocFile.getStr());
373 exit(99);
376 //yydebug = 0 no trace information
377 //yydebug = 1 parser produce trace information
378 yydebug = 0;
380 yyparse();
381 sal_Int32 nErrors = idlc()->getErrorCount();
383 fclose(yyin);
384 if (unlink(preprocFile.getStr()) != 0)
386 fprintf(stderr, "%s: Could not remove parser input file %s\n",
387 pOptions->getProgramName().getStr(), preprocFile.getStr());
388 exit(99);
391 return nErrors;
394 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */