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