1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_idlc.hxx" 30 #include <idlc/idlc.hxx> 31 #include <rtl/ustring.hxx> 32 #include <rtl/strbuf.hxx> 33 #include <osl/process.h> 34 #include <osl/diagnose.h> 35 #include <osl/thread.h> 36 #include <osl/file.hxx> 37 38 #if defined(SAL_W32) || defined(SAL_OS2) 39 #include <io.h> 40 #endif 41 42 #ifdef SAL_UNX 43 #include <unistd.h> 44 #if defined(MACOSX) || defined(FREEBSD) || defined(NETBSD) 45 #include <sys/wait.h> 46 #else 47 #include <wait.h> 48 #endif 49 #endif 50 51 #include <string.h> 52 53 using namespace ::rtl; 54 using namespace ::osl; 55 56 extern int yyparse(); 57 extern FILE* yyin; 58 extern int yydebug; 59 60 sal_Int32 lineNumber = 1; 61 62 63 static OUString TMP(RTL_CONSTASCII_USTRINGPARAM("TMP")); 64 static OUString TEMP(RTL_CONSTASCII_USTRINGPARAM("TEMP")); 65 static sal_Char tmpFilePattern[512]; 66 67 sal_Bool isFileUrl(const OString& fileName) 68 { 69 if (fileName.indexOf("file://") == 0 ) 70 return sal_True; 71 return sal_False; 72 } 73 74 OString convertToAbsoluteSystemPath(const OString& fileName) 75 { 76 OUString uSysFileName; 77 OUString uFileName(fileName.getStr(), fileName.getLength(), osl_getThreadTextEncoding()); 78 if ( isFileUrl(fileName) ) 79 { 80 if (FileBase::getSystemPathFromFileURL(uFileName, uSysFileName) 81 != FileBase::E_None) 82 { 83 OSL_ASSERT(false); 84 } 85 } else 86 { 87 OUString uWorkingDir, uUrlFileName, uTmp; 88 if (osl_getProcessWorkingDir(&uWorkingDir.pData) != osl_Process_E_None) 89 { 90 OSL_ASSERT(false); 91 } 92 if (FileBase::getFileURLFromSystemPath(uFileName, uTmp) 93 != FileBase::E_None) 94 { 95 OSL_ASSERT(false); 96 } 97 if (FileBase::getAbsoluteFileURL(uWorkingDir, uTmp, uUrlFileName) 98 != FileBase::E_None) 99 { 100 OSL_ASSERT(false); 101 } 102 if (FileBase::getSystemPathFromFileURL(uUrlFileName, uSysFileName) 103 != FileBase::E_None) 104 { 105 OSL_ASSERT(false); 106 } 107 } 108 109 return OUStringToOString(uSysFileName, osl_getThreadTextEncoding()); 110 } 111 112 OString convertToFileUrl(const OString& fileName) 113 { 114 if ( !isFileUrl(fileName) ) 115 { 116 OString tmp = convertToAbsoluteSystemPath(fileName); 117 OUString uFileName(tmp.getStr(), tmp.getLength(), osl_getThreadTextEncoding()); 118 OUString uUrlFileName; 119 if (FileBase::getFileURLFromSystemPath(uFileName, uUrlFileName) 120 != FileBase::E_None) 121 { 122 OSL_ASSERT(false); 123 } 124 return OUStringToOString(uUrlFileName, osl_getThreadTextEncoding()); 125 } 126 127 return fileName; 128 } 129 130 OString makeTempName(const OString& prefix) 131 { 132 OUString uTmpPath; 133 OString tmpPath; 134 135 if ( osl_getEnvironment(TMP.pData, &uTmpPath.pData) != osl_Process_E_None ) 136 { 137 if ( osl_getEnvironment(TEMP.pData, &uTmpPath.pData) != osl_Process_E_None ) 138 { 139 #if defined(SAL_W32) 140 tmpPath = OString("c:\\temp"); 141 #else 142 tmpPath = OString("/tmp"); 143 #endif 144 } 145 } 146 147 if ( uTmpPath.getLength() ) 148 tmpPath = OUStringToOString(uTmpPath, RTL_TEXTENCODING_UTF8); 149 150 #if defined(SAL_W32) || defined(SAL_UNX) || defined(SAL_OS2) 151 152 OSL_ASSERT( sizeof(tmpFilePattern) > ( strlen(tmpPath) 153 + RTL_CONSTASCII_LENGTH( 154 PATH_SEPARATOR ) 155 + prefix.getLength() 156 + RTL_CONSTASCII_LENGTH( 157 "XXXXXX") ) ); 158 159 tmpFilePattern[ sizeof(tmpFilePattern)-1 ] = '\0'; 160 strncpy(tmpFilePattern, tmpPath, sizeof(tmpFilePattern)-1); 161 strncat(tmpFilePattern, PATH_SEPARATOR, sizeof(tmpFilePattern)-1-strlen(tmpFilePattern)); 162 strncat(tmpFilePattern, prefix.getStr(), sizeof(tmpFilePattern)-1-strlen(tmpFilePattern)); 163 strncat(tmpFilePattern, "XXXXXX", sizeof(tmpFilePattern)-1-strlen(tmpFilePattern)); 164 165 #ifdef SAL_UNX 166 int nDescriptor = mkstemp(tmpFilePattern); 167 if( -1 == nDescriptor ) 168 { 169 fprintf( stderr,"idlc: couldn't create temporary file\n" ); 170 exit( 1 ); 171 } 172 // the file shall later be reopened by stdio functions 173 close( nDescriptor ); 174 #else 175 (void) mktemp(tmpFilePattern); 176 #endif 177 #endif 178 179 return OString(tmpFilePattern); 180 } 181 182 sal_Bool copyFile(const OString* source, const OString& target) 183 { 184 sal_Bool bRet = sal_True; 185 186 FILE* pSource = source == 0 ? stdin : fopen(source->getStr(), "rb"); 187 188 if ( !pSource ) 189 return sal_False; 190 191 FILE* pTarget = fopen(target.getStr(), "wb"); 192 193 if ( !pTarget ) 194 { 195 fclose(pSource); 196 return sal_False; 197 } 198 199 size_t totalSize = 512; 200 size_t readSize = 0; 201 size_t writeSize = 0; 202 char pBuffer[513]; 203 204 while ( !feof(pSource) ) 205 { 206 if ( (readSize = fread(pBuffer, 1, totalSize, pSource)) > 0 && !ferror(pSource) ) 207 { 208 if ( (writeSize = fwrite(pBuffer, 1, readSize, pTarget)) != readSize || ferror(pTarget) ) 209 { 210 if (source != 0) { 211 fclose(pSource); 212 } 213 fclose(pTarget); 214 return sal_False; 215 } 216 } 217 } 218 219 if (source != 0) { 220 fclose(pSource); 221 } 222 if ( fflush(pTarget) ) 223 bRet = sal_False; 224 fclose(pTarget); 225 226 return bRet; 227 } 228 229 sal_Int32 compileFile(const OString * pathname) 230 { 231 // preprocess input file 232 OString tmpFile = makeTempName(OString("idli_")); 233 OString preprocFile = makeTempName(OString("idlf_")); 234 235 OString fileName; 236 if (pathname == 0) { 237 fileName = "stdin"; 238 } else { 239 fileName = *pathname; 240 } 241 242 if ( !copyFile(pathname, tmpFile) ) 243 { 244 fprintf(stderr, "%s: could not copy %s%s to %s\n", 245 idlc()->getOptions()->getProgramName().getStr(), 246 pathname == 0 ? "" : "file ", fileName.getStr(), 247 tmpFile.getStr()); 248 exit(99); 249 } 250 251 idlc()->setFileName(fileName); 252 idlc()->setMainFileName(fileName); 253 idlc()->setRealFileName(tmpFile); 254 255 OStringBuffer cppArgs(512); 256 cppArgs.append("-DIDL -Xi -Xc -+ -I."); 257 Options* pOptions = idlc()->getOptions(); 258 259 OString filePath; 260 sal_Int32 index = fileName.lastIndexOf(SEPARATOR); 261 262 if ( index > 0) 263 { 264 filePath = fileName.copy(0, index); 265 266 if ( filePath.getLength() ) 267 { 268 cppArgs.append(" -I\""); 269 cppArgs.append(filePath); 270 cppArgs.append("\""); 271 } 272 } 273 274 if ( pOptions->isValid("-D") ) 275 { 276 cppArgs.append(" "); 277 cppArgs.append(pOptions->getOption("-D")); 278 } 279 if ( pOptions->isValid("-I") ) 280 { 281 cppArgs.append(" "); 282 cppArgs.append(pOptions->getOption("-I")); 283 } 284 285 cppArgs.append(" \""); 286 cppArgs.append(tmpFile); 287 cppArgs.append("\" \""); 288 cppArgs.append(preprocFile); 289 cppArgs.append("\""); 290 291 OString cmdFileName = makeTempName(OString("idlc_")); 292 FILE* pCmdFile = fopen(cmdFileName, "w"); 293 294 if ( !pCmdFile ) 295 { 296 fprintf(stderr, "%s: couldn't open temporary file for preprocessor commands: %s\n", 297 idlc()->getOptions()->getProgramName().getStr(), cmdFileName.getStr()); 298 exit(99); 299 } 300 #ifdef SAL_OS2_00 301 char* tok = strtok( (char*)cppArgs.getStr(), " \t\n\r"); 302 while( tok) { 303 if (tok[strlen(tok)-1] == '\"') 304 tok[strlen(tok)-1] = '\0'; 305 if (*tok == '\"') 306 memcpy( tok, tok+1, strlen(tok)); 307 if (strlen(tok)>0) { 308 fputs(tok, pCmdFile); 309 fputc('\n', pCmdFile); 310 } 311 tok = strtok( NULL, " \t\n\r"); 312 } 313 #else 314 fprintf(pCmdFile, "%s", cppArgs.getStr()); 315 #endif 316 fclose(pCmdFile); 317 318 OUString cmdArg(RTL_CONSTASCII_USTRINGPARAM("@")); 319 cmdArg += OStringToOUString(cmdFileName, RTL_TEXTENCODING_UTF8); 320 321 OUString cpp; 322 OUString startDir; 323 if (osl_getExecutableFile(&cpp.pData) != osl_Process_E_None) { 324 OSL_ASSERT(false); 325 } 326 327 sal_Int32 idx= cpp.lastIndexOf(OUString( RTL_CONSTASCII_USTRINGPARAM("idlc")) ); 328 cpp = cpp.copy(0, idx); 329 330 #if defined(SAL_W32) || defined(SAL_OS2) 331 cpp += OUString( RTL_CONSTASCII_USTRINGPARAM("idlcpp.exe")); 332 #else 333 cpp += OUString( RTL_CONSTASCII_USTRINGPARAM("idlcpp")); 334 #endif 335 336 oslProcess hProcess = NULL; 337 oslProcessError procError = osl_Process_E_None; 338 339 procError = osl_executeProcess(cpp.pData, &cmdArg.pData, 1, osl_Process_WAIT, 340 0, startDir.pData, 0, 0, &hProcess); 341 342 oslProcessInfo hInfo; 343 hInfo.Size = (sal_uInt32)(sizeof(oslProcessInfo)); 344 if (osl_getProcessInfo(hProcess, osl_Process_EXITCODE, &hInfo) 345 != osl_Process_E_None) 346 { 347 OSL_ASSERT(false); 348 } 349 350 if ( procError || (hInfo.Code != 0) ) 351 { 352 if ( procError != osl_Process_E_None ) 353 fprintf(stderr, "%s: starting preprocessor failed\n", pOptions->getProgramName().getStr()); 354 else 355 fprintf(stderr, "%s: preprocessing %s%s failed\n", 356 pOptions->getProgramName().getStr(), 357 pathname == 0 ? "" : "file ", fileName.getStr()); 358 359 unlink(tmpFile.getStr()); 360 unlink(preprocFile.getStr()); 361 unlink(cmdFileName.getStr()); 362 osl_freeProcessHandle(hProcess); 363 exit(hInfo.Code ? hInfo.Code : 99); 364 } 365 osl_freeProcessHandle(hProcess); 366 367 if (unlink(tmpFile.getStr()) != 0) 368 { 369 fprintf(stderr, "%s: Could not remove cpp input file %s\n", 370 pOptions->getProgramName().getStr(), tmpFile.getStr()); 371 exit(99); 372 } 373 374 if (unlink(cmdFileName.getStr()) != 0) 375 { 376 fprintf(stderr, "%s: Could not remove unocpp command file %s\n", 377 pOptions->getProgramName().getStr(), cmdFileName.getStr()); 378 379 exit(99); 380 } 381 382 if ( pOptions->isValid("-E") ) 383 { 384 if (unlink(preprocFile) != 0) 385 { 386 fprintf(stderr, "%s: Could not remove parser input file %s\n", 387 pOptions->getProgramName().getStr(), preprocFile.getStr()); 388 exit(99); 389 } 390 exit(0); 391 } 392 393 // parse file 394 yyin = fopen(preprocFile.getStr(), "r"); 395 if (yyin == NULL) 396 { 397 fprintf(stderr, "%s: Could not open cpp output file %s\n", 398 pOptions->getProgramName().getStr(), preprocFile.getStr()); 399 exit(99); 400 } 401 402 //yydebug = 0 no trace information 403 //yydebug = 1 parser produce trace information 404 yydebug = 0; 405 406 sal_Int32 nErrors = yyparse(); 407 nErrors = idlc()->getErrorCount(); 408 409 fclose(yyin); 410 if (unlink(preprocFile.getStr()) != 0) 411 { 412 fprintf(stderr, "%s: Could not remove parser input file %s\n", 413 pOptions->getProgramName().getStr(), preprocFile.getStr()); 414 exit(99); 415 } 416 417 return nErrors; 418 } 419