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