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