Version 4.0.0.1, tag libreoffice-4.0.0.1
[LibreOffice.git] / idlc / source / idlccompile.cxx
blob1acbf8440edeeb2b2eac99ac7946ea985930837c
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 ::rtl;
46 using namespace ::osl;
48 extern int yyparse();
49 extern FILE* yyin;
50 extern int yydebug;
52 sal_Int32 lineNumber = 1;
55 static OUString TMP(RTL_CONSTASCII_USTRINGPARAM("TMP"));
56 static OUString TEMP(RTL_CONSTASCII_USTRINGPARAM("TEMP"));
57 static sal_Char tmpFilePattern[512];
59 sal_Bool isFileUrl(const OString& fileName)
61 if (fileName.indexOf("file://") == 0 )
62 return sal_True;
63 return sal_False;
66 OString convertToAbsoluteSystemPath(const OString& fileName)
68 OUString uSysFileName;
69 OUString uFileName(fileName.getStr(), fileName.getLength(), osl_getThreadTextEncoding());
70 if ( isFileUrl(fileName) )
72 if (FileBase::getSystemPathFromFileURL(uFileName, uSysFileName)
73 != FileBase::E_None)
75 OSL_ASSERT(false);
77 } else
79 OUString uWorkingDir, uUrlFileName, uTmp;
80 if (osl_getProcessWorkingDir(&uWorkingDir.pData) != osl_Process_E_None)
82 OSL_ASSERT(false);
84 if (FileBase::getFileURLFromSystemPath(uFileName, uTmp)
85 != FileBase::E_None)
87 OSL_ASSERT(false);
89 if (FileBase::getAbsoluteFileURL(uWorkingDir, uTmp, uUrlFileName)
90 != FileBase::E_None)
92 OSL_ASSERT(false);
94 if (FileBase::getSystemPathFromFileURL(uUrlFileName, uSysFileName)
95 != FileBase::E_None)
97 OSL_ASSERT(false);
101 return OUStringToOString(uSysFileName, osl_getThreadTextEncoding());
104 OString convertToFileUrl(const OString& fileName)
106 if ( !isFileUrl(fileName) )
108 OString tmp = convertToAbsoluteSystemPath(fileName);
109 OUString uFileName(tmp.getStr(), tmp.getLength(), osl_getThreadTextEncoding());
110 OUString uUrlFileName;
111 if (FileBase::getFileURLFromSystemPath(uFileName, uUrlFileName)
112 != FileBase::E_None)
114 OSL_ASSERT(false);
116 return OUStringToOString(uUrlFileName, osl_getThreadTextEncoding());
119 return fileName;
122 OString makeTempName(const OString& prefix)
124 OUString uTmpPath;
125 OString tmpPath;
127 if ( osl_getEnvironment(TMP.pData, &uTmpPath.pData) != osl_Process_E_None )
129 if ( osl_getEnvironment(TEMP.pData, &uTmpPath.pData) != osl_Process_E_None )
131 #if defined(SAL_W32)
132 tmpPath = OString("c:\\temp");
133 #else
134 tmpPath = OString("/tmp");
135 #endif
139 if ( !uTmpPath.isEmpty() )
140 tmpPath = OUStringToOString(uTmpPath, RTL_TEXTENCODING_UTF8);
142 #if defined(SAL_W32) || defined(SAL_UNX)
144 OSL_ASSERT( sizeof(tmpFilePattern) >
145 (size_t) ( tmpPath.getLength()
146 + RTL_CONSTASCII_LENGTH( PATH_SEPARATOR )
147 + prefix.getLength()
148 + RTL_CONSTASCII_LENGTH( "XXXXXX") ) );
150 tmpFilePattern[ sizeof(tmpFilePattern)-1 ] = '\0';
151 strncpy(tmpFilePattern, tmpPath.getStr(), sizeof(tmpFilePattern)-1);
152 strncat(tmpFilePattern, PATH_SEPARATOR, sizeof(tmpFilePattern)-1-strlen(tmpFilePattern));
153 strncat(tmpFilePattern, prefix.getStr(), sizeof(tmpFilePattern)-1-strlen(tmpFilePattern));
154 strncat(tmpFilePattern, "XXXXXX", sizeof(tmpFilePattern)-1-strlen(tmpFilePattern));
156 #ifdef SAL_UNX
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 sal_Bool copyFile(const OString* source, const OString& target)
175 sal_Bool bRet = sal_True;
177 FILE* pSource = source == 0 ? stdin : fopen(source->getStr(), "rb");
178 if ( !pSource )
179 return sal_False;
181 FILE* pTarget = fopen(target.getStr(), "wb");
182 if ( !pTarget )
184 fclose(pSource);
185 return sal_False;
188 size_t totalSize = 512;
189 size_t readSize = 0;
190 char pBuffer[513];
192 while ( !feof(pSource) )
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 sal_False;
207 if (source != 0) {
208 fclose(pSource);
210 if ( fflush(pTarget) )
211 bRet = sal_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< ::rtl::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(rtl::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(rtl::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(rtl::OStringToOUString("-I" + token, RTL_TEXTENCODING_UTF8));
289 } while( nIndex != -1 );
292 lCppArgs.push_back(OUString(RTL_CONSTASCII_USTRINGPARAM("-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 += OUString( RTL_CONSTASCII_USTRINGPARAM("ucpp.exe"));
312 #else
313 cpp += OUString( RTL_CONSTASCII_USTRINGPARAM("ucpp"));
314 #endif
315 #else // SYSTEM_UCPP
316 cpp = OUString( RTL_CONSTASCII_USTRINGPARAM(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 = (rtl_uString**)rtl_allocateZeroMemory(nCmdArgs * sizeof(rtl_uString*));
325 ::std::vector< ::rtl::OUString >::iterator iter = lCppArgs.begin();
326 ::std::vector< ::rtl::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: */