Branch data 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 : 166 : static OUString TMP(RTL_CONSTASCII_USTRINGPARAM("TMP"));
56 : 166 : static OUString TEMP(RTL_CONSTASCII_USTRINGPARAM("TEMP"));
57 : : static sal_Char tmpFilePattern[512];
58 : :
59 : 47821 : sal_Bool isFileUrl(const OString& fileName)
60 : : {
61 [ + + ]: 47821 : if (fileName.indexOf("file://") == 0 )
62 : 17933 : return sal_True;
63 : 47821 : return sal_False;
64 : : }
65 : :
66 : 29888 : OString convertToAbsoluteSystemPath(const OString& fileName)
67 : : {
68 : 29888 : OUString uSysFileName;
69 [ + - ][ + - ]: 29888 : OUString uFileName(fileName.getStr(), fileName.getLength(), osl_getThreadTextEncoding());
70 [ + - ][ + + ]: 29888 : if ( isFileUrl(fileName) )
71 : : {
72 [ + - ]: 11955 : if (FileBase::getSystemPathFromFileURL(uFileName, uSysFileName)
73 : : != FileBase::E_None)
74 : : {
75 : : OSL_ASSERT(false);
76 : : }
77 : : } else
78 : : {
79 : 17933 : OUString uWorkingDir, uUrlFileName, uTmp;
80 [ + - ]: 17933 : if (osl_getProcessWorkingDir(&uWorkingDir.pData) != osl_Process_E_None)
81 : : {
82 : : OSL_ASSERT(false);
83 : : }
84 [ + - ]: 17933 : if (FileBase::getFileURLFromSystemPath(uFileName, uTmp)
85 : : != FileBase::E_None)
86 : : {
87 : : OSL_ASSERT(false);
88 : : }
89 [ + - ]: 17933 : if (FileBase::getAbsoluteFileURL(uWorkingDir, uTmp, uUrlFileName)
90 : : != FileBase::E_None)
91 : : {
92 : : OSL_ASSERT(false);
93 : : }
94 [ + - ]: 17933 : if (FileBase::getSystemPathFromFileURL(uUrlFileName, uSysFileName)
95 : : != FileBase::E_None)
96 : : {
97 : : OSL_ASSERT(false);
98 : 17933 : }
99 : : }
100 : :
101 [ + - ][ + - ]: 29888 : return OUStringToOString(uSysFileName, osl_getThreadTextEncoding());
102 : : }
103 : :
104 : 17933 : OString convertToFileUrl(const OString& fileName)
105 : : {
106 [ + + ]: 17933 : if ( !isFileUrl(fileName) )
107 : : {
108 [ + - ]: 11955 : OString tmp = convertToAbsoluteSystemPath(fileName);
109 [ + - ][ + - ]: 11955 : OUString uFileName(tmp.getStr(), tmp.getLength(), osl_getThreadTextEncoding());
110 : 11955 : OUString uUrlFileName;
111 [ + - ]: 11955 : if (FileBase::getFileURLFromSystemPath(uFileName, uUrlFileName)
112 : : != FileBase::E_None)
113 : : {
114 : : OSL_ASSERT(false);
115 : : }
116 [ + - ][ + - ]: 11955 : return OUStringToOString(uUrlFileName, osl_getThreadTextEncoding());
117 : : }
118 : :
119 : 17933 : return fileName;
120 : : }
121 : :
122 : 11956 : OString makeTempName(const OString& prefix)
123 : : {
124 : 11956 : OUString uTmpPath;
125 : 11956 : OString tmpPath;
126 : :
127 [ + - ][ + - ]: 11956 : if ( osl_getEnvironment(TMP.pData, &uTmpPath.pData) != osl_Process_E_None )
128 : : {
129 [ + - ][ + - ]: 11956 : 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 : 11956 : tmpPath = OString("/tmp");
135 : : #endif
136 : : }
137 : : }
138 : :
139 [ - + ]: 11956 : 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 : 11956 : tmpFilePattern[ sizeof(tmpFilePattern)-1 ] = '\0';
151 : 11956 : strncpy(tmpFilePattern, tmpPath.getStr(), sizeof(tmpFilePattern)-1);
152 : 11956 : strncat(tmpFilePattern, PATH_SEPARATOR, sizeof(tmpFilePattern)-1-strlen(tmpFilePattern));
153 : 11956 : strncat(tmpFilePattern, prefix.getStr(), sizeof(tmpFilePattern)-1-strlen(tmpFilePattern));
154 : 11956 : strncat(tmpFilePattern, "XXXXXX", sizeof(tmpFilePattern)-1-strlen(tmpFilePattern));
155 : :
156 : : #ifdef SAL_UNX
157 [ + - ]: 11956 : int nDescriptor = mkstemp(tmpFilePattern);
158 [ - + ]: 11956 : 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 [ + - ]: 11956 : close( nDescriptor );
165 : : #else
166 : : (void) mktemp(tmpFilePattern);
167 : : #endif
168 : : #endif
169 : :
170 : 11956 : return OString(tmpFilePattern);
171 : : }
172 : :
173 : 5978 : sal_Bool copyFile(const OString* source, const OString& target)
174 : : {
175 : 5978 : sal_Bool bRet = sal_True;
176 : :
177 [ + - ][ + - ]: 5978 : FILE* pSource = source == 0 ? stdin : fopen(source->getStr(), "rb");
178 [ - + ]: 5978 : if ( !pSource )
179 : 0 : return sal_False;
180 : :
181 [ + - ]: 5978 : FILE* pTarget = fopen(target.getStr(), "wb");
182 [ - + ]: 5978 : if ( !pTarget )
183 : : {
184 [ # # ]: 0 : fclose(pSource);
185 : 0 : return sal_False;
186 : : }
187 : :
188 : 5978 : size_t totalSize = 512;
189 : 5978 : size_t readSize = 0;
190 : : char pBuffer[513];
191 : :
192 [ + + ]: 37937 : while ( !feof(pSource) )
193 : : {
194 [ + - ][ + + ]: 31959 : if ( (readSize = fread(pBuffer, 1, totalSize, pSource)) > 0 && !ferror(pSource) )
[ + - ][ + + ]
195 : : {
196 [ + - ][ + - ]: 31952 : 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 [ + - ]: 5978 : if (source != 0) {
208 [ + - ]: 5978 : fclose(pSource);
209 : : }
210 [ + - ][ - + ]: 5978 : if ( fflush(pTarget) )
211 : 0 : bRet = sal_False;
212 [ + - ]: 5978 : fclose(pTarget);
213 : :
214 : 5978 : return bRet;
215 : : }
216 : :
217 : 5978 : sal_Int32 compileFile(const OString * pathname)
218 : : {
219 : : // preprocess input file
220 [ + - ]: 5978 : OString tmpFile = makeTempName(OString("idli_"));
221 [ + - ]: 5978 : OString preprocFile = makeTempName(OString("idlf_"));
222 : :
223 : 5978 : OString fileName;
224 [ - + ]: 5978 : if (pathname == 0) {
225 : 0 : fileName = "stdin";
226 : : } else {
227 : 5978 : fileName = *pathname;
228 : : }
229 : :
230 [ + - ][ - + ]: 5978 : 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 [ + - ][ + - ]: 5978 : idlc()->setFileName(fileName);
240 [ + - ]: 5978 : idlc()->setMainFileName(fileName);
241 [ + - ]: 5978 : idlc()->setRealFileName(tmpFile);
242 : :
243 [ + - ]: 5978 : ::std::vector< ::rtl::OUString> lCppArgs;
244 [ + - ]: 5978 : lCppArgs.push_back("-DIDL");
245 [ + - ]: 5978 : lCppArgs.push_back("-C");
246 [ + - ]: 5978 : lCppArgs.push_back("-zI");
247 : :
248 : 5978 : OStringBuffer cppArgs(256);
249 [ + - ]: 5978 : Options* pOptions = idlc()->getOptions();
250 : :
251 : 5978 : OString filePath;
252 : 5978 : sal_Int32 index = fileName.lastIndexOf(SEPARATOR);
253 : :
254 [ + - ]: 5978 : if ( index > 0)
255 : : {
256 : 5978 : filePath = fileName.copy(0, index);
257 : :
258 [ + - ]: 5978 : if ( !filePath.isEmpty() )
259 : : {
260 [ + - ]: 5978 : cppArgs.append("-I");
261 [ + - ]: 5978 : cppArgs.append(filePath);
262 : : lCppArgs.push_back(rtl::OStringToOUString(
263 : : cppArgs.makeStringAndClear().replace('\\', '/'),
264 [ + - ][ + - ]: 5978 : RTL_TEXTENCODING_UTF8));
265 : : }
266 : : }
267 : :
268 [ + - ][ - + ]: 5978 : 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(rtl::OStringToOUString("-D" + token, RTL_TEXTENCODING_UTF8));
277 : 0 : } while( nIndex != -1 );
278 : : }
279 : :
280 [ + - ][ + - ]: 5978 : if ( pOptions->isValid("-I") )
281 : : {
282 [ + - ]: 5978 : OString token, incOpt = pOptions->getOption("-I");
283 : 5978 : sal_Int32 nIndex = 0;
284 [ + + ]: 11951 : do
285 : : {
286 : 11951 : token = incOpt.getToken( 0, ' ', nIndex );
287 [ + - ]: 11951 : if (token.getLength())
288 [ + - ][ + - ]: 11951 : lCppArgs.push_back(rtl::OStringToOUString("-I" + token, RTL_TEXTENCODING_UTF8));
289 : 5978 : } while( nIndex != -1 );
290 : : }
291 : :
292 [ + - ][ + - ]: 5978 : lCppArgs.push_back(OUString(RTL_CONSTASCII_USTRINGPARAM("-o")));
293 : :
294 [ + - ]: 5978 : cppArgs.append(preprocFile);
295 [ + - ][ + - ]: 5978 : lCppArgs.push_back(OStringToOUString(cppArgs.makeStringAndClear(), RTL_TEXTENCODING_UTF8));
296 : :
297 [ + - ]: 5978 : cppArgs.append(tmpFile);
298 [ + - ][ + - ]: 5978 : lCppArgs.push_back(OStringToOUString(cppArgs.makeStringAndClear(), RTL_TEXTENCODING_UTF8));
299 : :
300 : 5978 : OUString cpp;
301 : 5978 : OUString startDir;
302 [ + - ]: 5978 : if (osl_getExecutableFile(&cpp.pData) != osl_Process_E_None) {
303 : : OSL_ASSERT(false);
304 : : }
305 : :
306 : 5978 : sal_Int32 idx= cpp.lastIndexOf("idlc");
307 : 5978 : cpp = cpp.copy(0, idx);
308 : :
309 : : #if defined(SAL_W32)
310 : : cpp += OUString( RTL_CONSTASCII_USTRINGPARAM("ucpp.exe"));
311 : : #else
312 [ + - ]: 5978 : cpp += OUString( RTL_CONSTASCII_USTRINGPARAM("ucpp"));
313 : : #endif
314 : :
315 : 5978 : oslProcess hProcess = NULL;
316 : 5978 : oslProcessError procError = osl_Process_E_None;
317 : :
318 : 5978 : const int nCmdArgs = lCppArgs.size();
319 : 5978 : rtl_uString** pCmdArgs = 0;
320 : 5978 : pCmdArgs = (rtl_uString**)rtl_allocateZeroMemory(nCmdArgs * sizeof(rtl_uString*));
321 : :
322 : 5978 : ::std::vector< ::rtl::OUString >::iterator iter = lCppArgs.begin();
323 : 5978 : ::std::vector< ::rtl::OUString >::iterator end = lCppArgs.end();
324 : 5978 : int i = 0;
325 [ + - ][ + + ]: 59775 : while ( iter != end ) {
326 : 53797 : pCmdArgs[i++] = (*iter).pData;
327 : 53797 : ++iter;
328 : : }
329 : :
330 : : procError = osl_executeProcess( cpp.pData, pCmdArgs, nCmdArgs, osl_Process_WAIT,
331 [ + - ]: 5978 : 0, startDir.pData, 0, 0, &hProcess );
332 : :
333 : : oslProcessInfo hInfo;
334 : 5978 : hInfo.Size = (sal_uInt32)(sizeof(oslProcessInfo));
335 [ + - ]: 5978 : if (osl_getProcessInfo(hProcess, osl_Process_EXITCODE, &hInfo)
336 : : != osl_Process_E_None)
337 : : {
338 : : OSL_ASSERT(false);
339 : : }
340 : :
341 [ + - ][ - + ]: 5978 : if ( procError || (hInfo.Code != 0) )
342 : : {
343 [ # # ]: 0 : if ( procError != osl_Process_E_None )
344 [ # # ][ # # ]: 0 : fprintf(stderr, "%s: starting preprocessor failed\n", pOptions->getProgramName().getStr());
345 : : else
346 : : fprintf(stderr, "%s: preprocessing %s%s failed\n",
347 [ # # ]: 0 : pOptions->getProgramName().getStr(),
348 [ # # ][ # # ]: 0 : pathname == 0 ? "" : "file ", fileName.getStr());
349 : :
350 [ # # ]: 0 : osl_freeProcessHandle(hProcess);
351 : 0 : rtl_freeMemory(pCmdArgs);
352 [ # # ]: 0 : exit(hInfo.Code ? hInfo.Code : 99);
353 : : }
354 [ + - ]: 5978 : osl_freeProcessHandle(hProcess);
355 : 5978 : rtl_freeMemory(pCmdArgs);
356 : :
357 [ - + ]: 5978 : if (unlink(tmpFile.getStr()) != 0)
358 : : {
359 : : fprintf(stderr, "%s: Could not remove cpp input file %s\n",
360 [ # # ][ # # ]: 0 : pOptions->getProgramName().getStr(), tmpFile.getStr());
361 : 0 : exit(99);
362 : : }
363 : :
364 [ + - ][ - + ]: 5978 : if ( pOptions->isValid("-E") )
365 : : {
366 [ # # ]: 0 : if (unlink(preprocFile.getStr()) != 0)
367 : : {
368 : : fprintf(stderr, "%s: Could not remove parser input file %s\n",
369 [ # # ][ # # ]: 0 : pOptions->getProgramName().getStr(), preprocFile.getStr());
370 : 0 : exit(99);
371 : : }
372 : 0 : exit(0);
373 : : }
374 : :
375 : : // parse file
376 [ + - ]: 5978 : yyin = fopen(preprocFile.getStr(), "r");
377 [ - + ]: 5978 : if (yyin == NULL)
378 : : {
379 : : fprintf(stderr, "%s: Could not open cpp output file %s\n",
380 [ # # ][ # # ]: 0 : pOptions->getProgramName().getStr(), preprocFile.getStr());
381 : 0 : exit(99);
382 : : }
383 : :
384 : : //yydebug = 0 no trace information
385 : : //yydebug = 1 parser produce trace information
386 : 5978 : yydebug = 0;
387 : :
388 [ + - ]: 5978 : sal_Int32 nErrors = yyparse();
389 [ + - ]: 5978 : nErrors = idlc()->getErrorCount();
390 : :
391 [ + - ]: 5978 : fclose(yyin);
392 [ - + ]: 5978 : if (unlink(preprocFile.getStr()) != 0)
393 : : {
394 : : fprintf(stderr, "%s: Could not remove parser input file %s\n",
395 [ # # ][ # # ]: 0 : pOptions->getProgramName().getStr(), preprocFile.getStr());
396 : 0 : exit(99);
397 : : }
398 : :
399 : 5978 : return nErrors;
400 [ + - ][ + - ]: 498 : }
401 : :
402 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|