fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / idlc / source / idlccompile.cxx
blobfd4b58b72bc2db999a6ad89c6b8d7e4aaf820bb6
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/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>
28 #if defined(SAL_W32)
29 #include <io.h>
30 #endif
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
43 #include <string.h>
45 using namespace ::osl;
47 extern int yyparse();
48 extern FILE* yyin;
49 extern int yydebug;
51 sal_Int32 lineNumber = 1;
54 static const char TMP[] = "TMP";
55 static const char TEMP[] = "TEMP";
56 static sal_Char tmpFilePattern[512];
58 bool isFileUrl(const OString& fileName)
60 if (fileName.startsWith("file://") )
61 return true;
62 return false;
65 OString convertToAbsoluteSystemPath(const OString& fileName)
67 OUString uSysFileName;
68 OUString uFileName(fileName.getStr(), fileName.getLength(), osl_getThreadTextEncoding());
69 if ( isFileUrl(fileName) )
71 if (FileBase::getSystemPathFromFileURL(uFileName, uSysFileName)
72 != FileBase::E_None)
74 OSL_ASSERT(false);
76 } else
78 OUString uWorkingDir, uUrlFileName, uTmp;
79 if (osl_getProcessWorkingDir(&uWorkingDir.pData) != osl_Process_E_None)
81 OSL_ASSERT(false);
83 if (FileBase::getFileURLFromSystemPath(uFileName, uTmp)
84 != FileBase::E_None)
86 OSL_ASSERT(false);
88 if (FileBase::getAbsoluteFileURL(uWorkingDir, uTmp, uUrlFileName)
89 != FileBase::E_None)
91 OSL_ASSERT(false);
93 if (FileBase::getSystemPathFromFileURL(uUrlFileName, uSysFileName)
94 != FileBase::E_None)
96 OSL_ASSERT(false);
100 return OUStringToOString(uSysFileName, osl_getThreadTextEncoding());
103 OString convertToFileUrl(const OString& fileName)
105 if ( !isFileUrl(fileName) )
107 OString tmp = convertToAbsoluteSystemPath(fileName);
108 OUString uFileName(tmp.getStr(), tmp.getLength(), osl_getThreadTextEncoding());
109 OUString uUrlFileName;
110 if (FileBase::getFileURLFromSystemPath(uFileName, uUrlFileName)
111 != FileBase::E_None)
113 OSL_ASSERT(false);
115 return OUStringToOString(uUrlFileName, osl_getThreadTextEncoding());
118 return fileName;
121 OString makeTempName(const OString& prefix)
123 OUString uTmpPath;
124 OString tmpPath;
126 if ( osl_getEnvironment(OUString(TMP).pData, &uTmpPath.pData) != osl_Process_E_None )
128 if ( osl_getEnvironment(OUString(TEMP).pData, &uTmpPath.pData) != osl_Process_E_None )
130 #if defined(SAL_W32)
131 tmpPath = OString("c:\\temp");
132 #else
133 tmpPath = OString("/tmp");
134 #endif
138 if ( !uTmpPath.isEmpty() )
139 tmpPath = OUStringToOString(uTmpPath, RTL_TEXTENCODING_UTF8);
141 #if defined(SAL_W32) || defined(SAL_UNX)
143 OSL_ASSERT( sizeof(tmpFilePattern) >
144 (size_t) ( tmpPath.getLength()
145 + RTL_CONSTASCII_LENGTH( PATH_SEPARATOR )
146 + prefix.getLength()
147 + RTL_CONSTASCII_LENGTH( "XXXXXX") ) );
149 tmpFilePattern[ sizeof(tmpFilePattern)-1 ] = '\0';
150 strncpy(tmpFilePattern, tmpPath.getStr(), sizeof(tmpFilePattern)-1);
151 strncat(tmpFilePattern, PATH_SEPARATOR, sizeof(tmpFilePattern)-1-strlen(tmpFilePattern));
152 strncat(tmpFilePattern, prefix.getStr(), sizeof(tmpFilePattern)-1-strlen(tmpFilePattern));
153 strncat(tmpFilePattern, "XXXXXX", sizeof(tmpFilePattern)-1-strlen(tmpFilePattern));
155 #ifdef SAL_UNX
156 // coverity[secure_temp] - https://communities.coverity.com/thread/3179
157 int nDescriptor = mkstemp(tmpFilePattern);
158 if( -1 == nDescriptor )
160 fprintf(stderr, "idlc: mkstemp(\"%s\") failed: %s\n", tmpFilePattern, strerror(errno));
161 exit( 1 );
163 // the file shall later be reopened by stdio functions
164 close( nDescriptor );
165 #else
166 (void) mktemp(tmpFilePattern);
167 #endif
168 #endif
170 return OString(tmpFilePattern);
173 bool copyFile(const OString* source, const OString& target)
175 bool bRet = true;
177 FILE* pSource = source == 0 ? stdin : fopen(source->getStr(), "rb");
178 if ( !pSource )
179 return false;
181 FILE* pTarget = fopen(target.getStr(), "wb");
182 if ( !pTarget )
184 fclose(pSource);
185 return false;
188 size_t totalSize = 512;
189 char pBuffer[513];
191 while ( !feof(pSource) )
193 size_t readSize;
194 if ( (readSize = fread(pBuffer, 1, totalSize, pSource)) > 0 && !ferror(pSource) )
196 if ( (fwrite(pBuffer, 1, readSize, pTarget)) != readSize || ferror(pTarget) )
198 if (source != 0) {
199 fclose(pSource);
201 fclose(pTarget);
202 return false;
207 if (source != 0) {
208 fclose(pSource);
210 if ( fflush(pTarget) )
211 bRet = false;
212 fclose(pTarget);
214 return bRet;
217 sal_Int32 compileFile(const OString * pathname)
219 // preprocess input file
220 OString tmpFile = makeTempName(OString("idli_"));
221 OString preprocFile = makeTempName(OString("idlf_"));
223 OString fileName;
224 if (pathname == 0) {
225 fileName = "stdin";
226 } else {
227 fileName = *pathname;
230 if ( !copyFile(pathname, tmpFile) )
232 fprintf(stderr, "%s: could not copy %s%s to %s\n",
233 idlc()->getOptions()->getProgramName().getStr(),
234 pathname == 0 ? "" : "file ", fileName.getStr(),
235 tmpFile.getStr());
236 exit(99);
239 idlc()->setFileName(fileName);
240 idlc()->setMainFileName(fileName);
241 idlc()->setRealFileName(tmpFile);
243 ::std::vector< OUString> lCppArgs;
244 lCppArgs.push_back("-DIDL");
245 lCppArgs.push_back("-C");
246 lCppArgs.push_back("-zI");
248 OStringBuffer cppArgs(256);
249 Options* pOptions = idlc()->getOptions();
251 OString filePath;
252 sal_Int32 index = fileName.lastIndexOf(SEPARATOR);
254 if ( index > 0)
256 filePath = fileName.copy(0, index);
258 if ( !filePath.isEmpty() )
260 cppArgs.append("-I");
261 cppArgs.append(filePath);
262 lCppArgs.push_back(OStringToOUString(
263 cppArgs.makeStringAndClear().replace('\\', '/'),
264 RTL_TEXTENCODING_UTF8));
268 if ( pOptions->isValid("-D") )
270 OString token, dOpt = pOptions->getOption("-D");
271 sal_Int32 nIndex = 0;
274 token = dOpt.getToken( 0, ' ', nIndex );
275 if (token.getLength())
276 lCppArgs.push_back(OStringToOUString("-D" + token, RTL_TEXTENCODING_UTF8));
277 } while( nIndex != -1 );
280 if ( pOptions->isValid("-I") )
282 OString token, incOpt = pOptions->getOption("-I");
283 sal_Int32 nIndex = 0;
286 token = incOpt.getToken( 0, ' ', nIndex );
287 if (token.getLength())
288 lCppArgs.push_back(OStringToOUString("-I" + token, RTL_TEXTENCODING_UTF8));
289 } while( nIndex != -1 );
292 lCppArgs.push_back(OUString("-o"));
294 cppArgs.append(preprocFile);
295 lCppArgs.push_back(OStringToOUString(cppArgs.makeStringAndClear(), RTL_TEXTENCODING_UTF8));
297 cppArgs.append(tmpFile);
298 lCppArgs.push_back(OStringToOUString(cppArgs.makeStringAndClear(), RTL_TEXTENCODING_UTF8));
300 OUString cpp;
301 OUString startDir;
302 #ifndef SYSTEM_UCPP
303 if (osl_getExecutableFile(&cpp.pData) != osl_Process_E_None) {
304 OSL_ASSERT(false);
307 sal_Int32 idx= cpp.lastIndexOf("idlc");
308 cpp = cpp.copy(0, idx);
310 #if defined(SAL_W32)
311 cpp += "ucpp.exe";
312 #else
313 cpp += "ucpp";
314 #endif
315 #else // SYSTEM_UCPP
316 cpp = OUString(UCPP);
317 #endif
318 oslProcess hProcess = NULL;
319 oslProcessError procError = osl_Process_E_None;
321 const int nCmdArgs = lCppArgs.size();
322 rtl_uString** pCmdArgs = 0;
323 pCmdArgs = static_cast<rtl_uString**>(rtl_allocateZeroMemory(nCmdArgs * sizeof(rtl_uString*)));
325 ::std::vector< OUString >::iterator iter = lCppArgs.begin();
326 ::std::vector< OUString >::iterator end = lCppArgs.end();
327 int i = 0;
328 while ( iter != end ) {
329 pCmdArgs[i++] = (*iter).pData;
330 ++iter;
333 procError = osl_executeProcess( cpp.pData, pCmdArgs, nCmdArgs, osl_Process_WAIT,
334 0, startDir.pData, 0, 0, &hProcess );
336 oslProcessInfo hInfo;
337 hInfo.Size = (sal_uInt32)(sizeof(oslProcessInfo));
338 if (osl_getProcessInfo(hProcess, osl_Process_EXITCODE, &hInfo)
339 != osl_Process_E_None)
341 OSL_ASSERT(false);
344 if ( procError || (hInfo.Code != 0) )
346 if ( procError != osl_Process_E_None )
347 fprintf(stderr, "%s: starting preprocessor failed\n", pOptions->getProgramName().getStr());
348 else
349 fprintf(stderr, "%s: preprocessing %s%s failed\n",
350 pOptions->getProgramName().getStr(),
351 pathname == 0 ? "" : "file ", fileName.getStr());
353 osl_freeProcessHandle(hProcess);
354 rtl_freeMemory(pCmdArgs);
355 exit(hInfo.Code ? hInfo.Code : 99);
357 osl_freeProcessHandle(hProcess);
358 rtl_freeMemory(pCmdArgs);
360 if (unlink(tmpFile.getStr()) != 0)
362 fprintf(stderr, "%s: Could not remove cpp input file %s\n",
363 pOptions->getProgramName().getStr(), tmpFile.getStr());
364 exit(99);
367 if ( pOptions->isValid("-E") )
369 if (unlink(preprocFile.getStr()) != 0)
371 fprintf(stderr, "%s: Could not remove parser input file %s\n",
372 pOptions->getProgramName().getStr(), preprocFile.getStr());
373 exit(99);
375 exit(0);
378 // parse file
379 yyin = fopen(preprocFile.getStr(), "r");
380 if (yyin == NULL)
382 fprintf(stderr, "%s: Could not open cpp output file %s\n",
383 pOptions->getProgramName().getStr(), preprocFile.getStr());
384 exit(99);
387 //yydebug = 0 no trace information
388 //yydebug = 1 parser produce trace information
389 yydebug = 0;
391 sal_Int32 nErrors = yyparse();
392 nErrors = idlc()->getErrorCount();
394 fclose(yyin);
395 if (unlink(preprocFile.getStr()) != 0)
397 fprintf(stderr, "%s: Could not remove parser input file %s\n",
398 pOptions->getProgramName().getStr(), preprocFile.getStr());
399 exit(99);
402 return nErrors;
405 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */