- Timestamp:
- Jun 2, 2007 10:13:03 AM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kObjCache/kObjCache.c
r1001 r1002 37 37 #include <sys/stat.h> 38 38 #include <fcntl.h> 39 #include <limits.h> 40 #ifndef PATH_MAX 41 # define PATH_MAX _MAX_PATH /* windows */ 42 #endif 39 43 #if defined(__OS2__) || defined(__WIN__) 40 44 # include <process.h> … … 54 58 55 59 56 /* for later: */57 #define xmalloc malloc58 #define xrealloc realloc59 #define xstrdup strdup60 61 62 60 /******************************************************************************* 63 61 * Structures and Typedefs * … … 88 86 char *pszDir; 89 87 /** The name of the cache file. */ 90 c har *pszName;88 const char *pszName; 91 89 /** Set if the object needs to be (re)compiled. */ 92 90 unsigned fNeedCompiling; … … 137 135 *******************************************************************************/ 138 136 static const char *FindFilenameInPath(const char *pszPath); 137 static char *AbsPath(const char *pszPath); 139 138 static char *MakePathFromDirAndFile(const char *pszName, const char *pszDir); 140 139 static char *CalcRelativeName(const char *pszPath, const char *pszDir); … … 144 143 static int DoesFileInDirExist(const char *pszName, const char *pszDir); 145 144 static void *ReadFileInDir(const char *pszName, const char *pszDir, size_t *pcbFile); 145 static void *xmalloc(size_t); 146 static void *xrealloc(void *, size_t); 147 static char *xstrdup(const char *); 148 146 149 147 150 /* crc.c */ … … 172 175 173 176 /** 174 * Creates a cache entry for the given cache file name.175 *176 * @returns Pointer to a cache entry.177 * @param pszFilename The cache file name.178 */179 static PKOBJCACHE kObjCacheCreate(const char *pszFilename)180 {181 PKOBJCACHE pEntry;182 const char *pszDir;183 size_t cchDir;184 185 /*186 * Allocate an empty entry.187 */188 pEntry = xmalloc(sizeof(*pEntry));189 memset(pEntry, 0, sizeof(*pEntry));190 191 /*192 * Setup the directory and cache file name.193 */194 pszDir = pszFilename;195 assert(*pszFilename);196 pszFilename = FindFilenameInPath(pszFilename);197 if (pszFilename <= pszDir)198 {199 pszDir = "./";200 cchDir = 2;201 }202 else203 cchDir = pszFilename - pszDir; /* includes the separator */204 205 pEntry->pszDir = xmalloc(cchDir + 1);206 memcpy(pEntry->pszDir, pszDir, cchDir);207 pEntry->pszDir[cchDir] = '\0';208 pEntry->pszName = xstrdup(pszFilename);209 210 return pEntry;211 }212 213 214 #if 0 /* don't bother. */215 /**216 * Destroys the cache entry freeing up all it's resources.217 *218 * @param pEntry The entry to free.219 */220 static void kObjCacheDestroy(PKOBJCACHE pEntry)221 {222 free(pEntry->pszDir);223 free(pEntry->pszName);224 while (pEntry->SumHead.pNext)225 {226 void *pv = pEntry->SumHead.pNext;227 pEntry->SumHead.pNext = pEntry->SumHead.pNext->pNext;228 if (pv != &pEntry->NewSum)229 free(pv);230 }231 free(pEntry);232 }233 #endif234 235 236 /**237 177 * Print a fatal error message and exit with rc=1. 238 178 * … … 276 216 277 217 /** 218 * Creates a cache entry for the given cache file name. 219 * 220 * @returns Pointer to a cache entry. 221 * @param pszFilename The cache file name. 222 */ 223 static PKOBJCACHE kObjCacheCreate(const char *pszFilename) 224 { 225 PKOBJCACHE pEntry; 226 227 /* 228 * Allocate an empty entry. 229 */ 230 pEntry = xmalloc(sizeof(*pEntry)); 231 memset(pEntry, 0, sizeof(*pEntry)); 232 233 /* 234 * Setup the directory and cache file name. 235 */ 236 pEntry->pszDir = AbsPath(pszFilename); 237 pEntry->pszName = FindFilenameInPath(pEntry->pszDir); 238 if (pEntry->pszDir == pEntry->pszName) 239 kObjCacheFatal(pEntry, "Failed to find abs path for '%s'!\n", pszFilename); 240 ((char *)pEntry->pszName)[-1] = '\0'; 241 242 return pEntry; 243 } 244 245 246 #if 0 /* don't bother. */ 247 /** 248 * Destroys the cache entry freeing up all it's resources. 249 * 250 * @param pEntry The entry to free. 251 */ 252 static void kObjCacheDestroy(PKOBJCACHE pEntry) 253 { 254 free(pEntry->pszDir); 255 free(pEntry->pszName); 256 while (pEntry->SumHead.pNext) 257 { 258 void *pv = pEntry->SumHead.pNext; 259 pEntry->SumHead.pNext = pEntry->SumHead.pNext->pNext; 260 if (pv != &pEntry->NewSum) 261 free(pv); 262 } 263 free(pEntry); 264 } 265 #endif 266 267 268 /** 278 269 * Reads and parses the cache file. 279 270 * … … 282 273 static void kObjCacheRead(PKOBJCACHE pEntry) 283 274 { 284 275 kObjCacheVerbose(pEntry, "reading cache file...\n"); 276 pEntry->fNeedCompiling = 1; 285 277 } 286 278 … … 293 285 static void kObjCacheWrite(PKOBJCACHE pEntry) 294 286 { 287 kObjCacheVerbose(pEntry, "writing cache file...\n"); 295 288 296 289 } … … 304 297 * @param cArgv The number of arguments in the vector. 305 298 */ 306 static void kObjCacheSpawn(PCKOBJCACHE pEntry, const char **papszArgv, unsigned cArgv, const char *pszMsg) 307 { 308 #if defined(__OS2__) 309 int rc = _spawnvp(_P_WAIT, papszArgv[0], papszArgv); 310 if (rc) 311 kObjCacheFatal(pEntry, "%s - _spawnvp / command failed, rc=%#x\n", pszMsg, rc); 312 313 #elif defined(__WIN__) 314 intptr_t rc = _spawnvp(_P_WAIT, papszArgv[0], papszArgv); 315 if (rc) 316 kObjCacheFatal(pEntry, "%s - _spawnvp / command failed, rc=0x%p\n", pszMsg, rc); 299 static void kObjCacheSpawn(PCKOBJCACHE pEntry, const char **papszArgv, unsigned cArgv, const char *pszMsg, const char *pszStdOut) 300 { 301 #if defined(__OS2__) || defined(__WIN__) 302 intptr_t rc; 303 int fdStdOut = -1; 304 if (pszStdOut) 305 { 306 int fdReDir; 307 fdStdOut = dup(1); /* dup2(1,-1) doesn't work right on windows */ 308 close(1); 309 fdReDir = open(pszStdOut, O_CREAT | O_TRUNC | O_WRONLY, 0777); 310 if (fdReDir < 0) 311 kObjCacheFatal(pEntry, "%s - failed to create stdout redirection file '%s': %s\n", 312 pszMsg, pszStdOut, strerror(errno)); 313 if (fdReDir != 1) 314 { 315 if (dup2(fdReDir, 1) < 0) 316 kObjCacheFatal(pEntry, "%s - dup2 failed: %s\n", pszMsg, strerror(errno)); 317 close(fdReDir); 318 } 319 } 320 321 errno = 0; 322 rc = _spawnvp(_P_WAIT, papszArgv[0], papszArgv); 323 if (rc < 0) 324 kObjCacheFatal(pEntry, "%s - _spawnvp failed (rc=0x%p): %s\n", pszMsg, rc, strerror(errno)); 325 if (rc > 0) 326 kObjCacheFatal(pEntry, "%s - failed rc=%d\n", pszMsg, (int)rc); 327 if (fdStdOut) 328 { 329 close(1); 330 fdStdOut = dup2(fdStdOut, 1); 331 close(fdStdOut); 332 } 317 333 318 334 #else … … 322 338 if (!pid) 323 339 { 340 if (pszStdOut) 341 { 342 close(1); 343 fdReDir = open(pszStdOut, O_CREAT | O_TRUNC | O_WRONLY, 0777); 344 if (fdReDir < 0) 345 kObjCacheFatal(pEntry, "%s - failed to create stdout redirection file '%s': %s\n", 346 pszMsg, pszStdOut, strerror(errno)); 347 if (fdReDir != 1) 348 { 349 if (dup2(fdReDir, 1) < 0) 350 kObjCacheFatal(pEntry, "%s - dup2 failed: %s\n", pszMsg, strerror(errno)); 351 close(fdReDir); 352 } 353 } 354 324 355 execvp(papszArgv[0], papszArgv); 325 356 kObjCacheFatal(pEntry, "%s - execvp failed rc=%d errno=%d %s\n", … … 357 388 */ 358 389 pEntry->pszNewCppMapping = ReadFileInDir(pEntry->pszNewCppName, pEntry->pszDir, &pEntry->cbNewCppMapping); 359 if ( pEntry->pszNewCppMapping)390 if (!pEntry->pszNewCppMapping) 360 391 kObjCacheFatal(pEntry, "failed to open/read '%s' in '%s': %s\n", 361 392 pEntry->pszNewCppName, pEntry->pszDir, strerror(errno)); 393 kObjCacheVerbose(pEntry, "precompiled file is %lu bytes long\n", (unsigned long)pEntry->cbNewCppMapping); 362 394 363 395 pEntry->NewSum.crc32 = crc32(0, pEntry->pszNewCppMapping, pEntry->cbNewCppMapping); … … 365 397 MD5Update(&MD5Ctx, pEntry->pszNewCppMapping, pEntry->cbNewCppMapping); 366 398 MD5Final(&pEntry->NewSum.md5[0], &MD5Ctx); 399 kObjCacheVerbose(pEntry, "crc32=%#lx md5=08x%08x%08x%08x\n", pEntry->NewSum.crc32, 400 ((uint32_t *)&pEntry->NewSum.md5[0])[0], 401 ((uint32_t *)&pEntry->NewSum.md5[0])[1], 402 ((uint32_t *)&pEntry->NewSum.md5[0])[2], 403 ((uint32_t *)&pEntry->NewSum.md5[0])[3]); 367 404 } 368 405 … … 375 412 * @param cArgvPreComp The number of arguments. 376 413 * @param pszPreCompName Precompile output name. (must kick around) 377 */ 378 static void kObjCachePreCompile(PKOBJCACHE pEntry, const char **papszArgvPreComp, unsigned cArgvPreComp, const char *pszPreCompName) 414 * @param fRedirStdOut Whether stdout needs to be redirected or not. 415 */ 416 static void kObjCachePreCompile(PKOBJCACHE pEntry, const char **papszArgvPreComp, unsigned cArgvPreComp, const char *pszPreCompName, int fRedirStdOut) 379 417 { 380 418 /* … … 383 421 * we might with to do a quick matchup later we can't remove it just now. 384 422 */ 385 if (pEntry->pszOldCppName) 423 if ( pEntry->pszOldCppName 424 && DoesFileInDirExist(pEntry->pszOldCppName, pEntry->pszDir)) 386 425 { 387 426 size_t cch = strlen(pEntry->pszOldCppName); … … 390 429 memcpy(psz + cch, "-old", sizeof("-old")); 391 430 431 kObjCacheVerbose(pEntry, "renaming '%s' to '%s' in '%s'\n", pEntry->pszOldCppName, psz, pEntry->pszDir); 392 432 UnlinkFileInDir(psz, pEntry->pszDir); 393 433 if (RenameFileInDir(pEntry->pszOldCppName, psz, pEntry->pszDir)) … … 397 437 pEntry->pszOldCppName = psz; 398 438 } 399 pEntry->pszNewCppName = pszPreCompName;439 pEntry->pszNewCppName = CalcRelativeName(pszPreCompName, pEntry->pszDir); 400 440 401 441 /* 402 442 * Precompile it and calculate the checksum on the output. 403 443 */ 404 if (!pszPreCompName) 405 { 406 kObjCacheFatal(pEntry, "redirection feature is not implemented\n"); 407 /** @todo piped output. */ 408 } 409 kObjCacheSpawn(pEntry, papszArgvPreComp, cArgvPreComp, "precompile"); 444 kObjCacheVerbose(pEntry, "precompiling -> '%s'...\n", pEntry->pszNewCppName); 445 if (fRedirStdOut) 446 kObjCacheSpawn(pEntry, papszArgvPreComp, cArgvPreComp, "precompile", pszPreCompName); 447 else 448 kObjCacheSpawn(pEntry, papszArgvPreComp, cArgvPreComp, "precompile", NULL); 410 449 kObjCacheCalcChecksum(pEntry); 411 450 } … … 449 488 pEntry->pszObjName = NULL; 450 489 } 451 pEntry->pszNewObjName = CalcRelativeName(p Entry->pszDir, pszObjName);490 pEntry->pszNewObjName = CalcRelativeName(pszObjName, pEntry->pszDir); 452 491 453 492 /* … … 462 501 * Do the recompilation. 463 502 */ 503 kObjCacheVerbose(pEntry, "compiling -> '%s'...\n", pEntry->pszNewObjName); 464 504 pEntry->papszArgvCompile = papszArgvCompile; 465 505 pEntry->cArgvCompile = cArgvCompile; 466 kObjCacheSpawn(pEntry, papszArgvCompile, cArgvCompile, "compile" );506 kObjCacheSpawn(pEntry, papszArgvCompile, cArgvCompile, "compile", NULL); 467 507 } 468 508 … … 482 522 * Does the object name differ? 483 523 */ 484 if ( !pEntry->fNeedCompiling 485 && strcmp(FindFilenameInPath(pszObjName), pEntry->pszObjName)) 486 { 487 pEntry->fNeedCompiling = 1; 488 kObjCacheVerbose(pEntry, "object name changed\n"); 524 if (!pEntry->fNeedCompiling) 525 { 526 char *pszTmp = CalcRelativeName(pszObjName, pEntry->pszDir); 527 if (strcmp(pEntry->pszObjName, pszTmp)) 528 { 529 pEntry->fNeedCompiling = 1; 530 kObjCacheVerbose(pEntry, "object name changed '%s' -> '%s'\n", pEntry->pszObjName, pszTmp); 531 } 532 free(pszTmp); 489 533 } 490 534 … … 514 558 * Does the object file exist? 515 559 */ 516 if (!DoesFileInDirExist(pEntry->pszObjName, pEntry->pszDir)) 560 if ( !pEntry->fNeedCompiling 561 && !DoesFileInDirExist(pEntry->pszObjName, pEntry->pszDir)) 517 562 { 518 563 pEntry->fNeedCompiling = 1; … … 562 607 if (pEntry->fNeedCompiling) 563 608 kObjCacheCompileIt(pEntry, papszArgvCompile, cArgvCompile, pszObjName); 609 } 610 611 612 /** 613 * Gets the absolute path 614 * 615 * @returns A new heap buffer containing the absolute path. 616 * @param pszPath The path to make absolute. (Readonly) 617 */ 618 static char *AbsPath(const char *pszPath) 619 { 620 char szTmp[PATH_MAX]; 621 #if defined(__OS2__) || defined(__WIN__) 622 if (!_fullpath(szTmp, *pszPath ? pszPath : ".", sizeof(szTmp))) 623 return xstrdup(pszPath); 624 #else 625 if (!realpath(pszPath, szTmp)) 626 return xstrdup(pszPath); 627 #endif 628 return xstrdup(szTmp); 564 629 } 565 630 … … 610 675 611 676 /** 612 * Calculate how to get to pszPath from pszDir. 613 * 614 * @returns The relative path from pszDir to path pszPath. 615 * @param pszPath The path to the object. 616 * @param pszDir The directory it shall be relative to. 617 */ 618 static char *CalcRelativeName(const char *pszPath, const char *pszDir) 619 { 620 size_t cchDir = strlen(pszDir); 677 * Compares two path strings to see if they are identical. 678 * 679 * This doesn't do anything fancy, just the case ignoring and 680 * slash unification. 681 * 682 * @returns 1 if equal, 0 otherwise. 683 * @param pszPath1 The first path. 684 * @param pszPath2 The second path. 685 * @param cch The number of characters to compare. 686 */ 687 static int ArePathsIdentical(const char *pszPath1, const char *pszPath2, size_t cch) 688 { 621 689 #if defined(__OS2__) || defined(__WIN__) 622 int fMatches; 623 #endif 624 625 /* 626 * This is indeed a bit tricky, so we'll try the easy way first... 627 */ 628 #if defined(__OS2__) || defined(__WIN__) 629 fMatches = strnicmp(pszPath, pszDir, cchDir); 630 if (!fMatches) 690 if (strnicmp(pszPath1, pszPath2, cch)) 631 691 { 632 692 /* Slashes may differ, compare char by char. */ 633 const char *psz1 = pszDir; 634 const char *psz2 = pszPath; 635 fMatches = 1; 636 for (;; psz1++, psz2++) 693 const char *psz1 = pszPath1; 694 const char *psz2 = pszPath2; 695 for (;cch; psz1++, psz2++, cch--) 637 696 { 638 697 if (*psz1 != *psz2) 639 698 { 640 if (!*psz1) /* dir */641 break;642 699 if ( tolower(*psz1) != tolower(*psz2) 643 700 && toupper(*psz1) != toupper(*psz2) … … 646 703 && *psz2 != '/' 647 704 && *psz2 != '\\') 648 { 649 fMatches = 0; 650 break; 651 } 705 return 0; 652 706 } 653 707 } 654 708 } 655 if (fMatches)709 return 1; 656 710 #else 657 if (!strncmp(pszPath, pszDir, cchDir))711 return !strncmp(pszPath1, pszPath2, cch); 658 712 #endif 713 } 714 715 716 /** 717 * Calculate how to get to pszPath from pszDir. 718 * 719 * @returns The relative path from pszDir to path pszPath. 720 * @param pszPath The path to the object. 721 * @param pszDir The directory it shall be relative to. 722 */ 723 static char *CalcRelativeName(const char *pszPath, const char *pszDir) 724 { 725 char *pszRet = NULL; 726 char *pszAbsPath = NULL; 727 size_t cchDir = strlen(pszDir); 728 729 /* 730 * This is indeed a bit tricky, so we'll try the easy way first... 731 */ 732 if (ArePathsIdentical(pszPath, pszDir, cchDir)) 659 733 { 660 734 if (pszPath[cchDir]) 661 return xstrdup(pszPath + cchDir); 662 return xstrdup("./"); 735 pszRet = (char *)pszPath + cchDir; 736 else 737 pszRet = "./"; 738 } 739 else 740 { 741 pszAbsPath = AbsPath(pszPath); 742 if (ArePathsIdentical(pszAbsPath, pszDir, cchDir)) 743 { 744 if (pszPath[cchDir]) 745 pszRet = pszAbsPath + cchDir; 746 else 747 pszRet = "./"; 748 } 749 } 750 if (pszRet) 751 { 752 #if defined(__OS2__) || defined(__WIN__) 753 while (*pszRet == ':' || *pszRet == '/' || *pszRet == '\\') 754 #else 755 while (*pszRet == '/') 756 #endif 757 pszRet++; 758 pszRet = xstrdup(pszRet); 759 free(pszAbsPath); 760 return pszRet; 663 761 } 664 762 … … 795 893 796 894 895 static void *xmalloc(size_t cb) 896 { 897 void *pv = malloc(cb); 898 if (!pv) 899 kObjCacheFatal(NULL, "out of memory (%d)\n", (int)cb); 900 return pv; 901 } 902 903 904 static void *xrealloc(void *pvOld, size_t cb) 905 { 906 void *pv = realloc(pvOld, cb); 907 if (!pv) 908 kObjCacheFatal(NULL, "out of memory (%d)\n", (int)cb); 909 return pv; 910 } 911 912 913 static char *xstrdup(const char *pszIn) 914 { 915 char *psz = strdup(pszIn); 916 if (!psz) 917 kObjCacheFatal(NULL, "out of memory (%d)\n", (int)strlen(pszIn)); 918 return psz; 919 } 920 797 921 798 922 /** … … 820 944 static int usage(void) 821 945 { 822 printf("syntax: kObjCache [-v|--verbose] [-f|--file] <cache-file> [-V|--version] \n"946 printf("syntax: kObjCache [-v|--verbose] [-f|--file] <cache-file> [-V|--version] [-r|--redir-stdout]\n" 823 947 " --kObjCache-cpp <filename> <precompiler + args> \n" 824 948 " --kObjCache-cc <object> <compiler + args>\n" … … 839 963 unsigned cArgvPreComp = 0; 840 964 const char *pszPreCompName = NULL; 965 int fRedirStdOut = 0; 841 966 842 967 const char **papszArgvCompile = NULL; … … 866 991 { 867 992 enmMode = kOC_CcArgv; 868 if ( pszObjName)993 if (!pszObjName) 869 994 { 870 995 if (++i >= argc) … … 882 1007 { 883 1008 if (!(cArgvPreComp % 16)) 884 { 885 cArgvPreComp += 16; 886 papszArgvPreComp = xrealloc((void *)papszArgvPreComp, (cArgvPreComp + 2) * sizeof(papszArgvPreComp[0])); 887 } 1009 papszArgvPreComp = xrealloc((void *)papszArgvPreComp, (cArgvPreComp + 17) * sizeof(papszArgvPreComp[0])); 888 1010 papszArgvPreComp[cArgvPreComp++] = argv[i]; 889 1011 papszArgvPreComp[cArgvPreComp] = NULL; … … 892 1014 { 893 1015 if (!(cArgvCompile % 16)) 894 { 895 cArgvCompile += 16; 896 papszArgvCompile = xrealloc((void *)papszArgvCompile, (cArgvCompile + 2) * sizeof(papszArgvCompile[0])); 897 } 1016 papszArgvCompile = xrealloc((void *)papszArgvCompile, (cArgvCompile + 17) * sizeof(papszArgvCompile[0])); 898 1017 papszArgvCompile[cArgvCompile++] = argv[i]; 899 1018 papszArgvCompile[cArgvCompile] = NULL; … … 906 1025 pszCacheFile = argv[++i]; 907 1026 } 1027 else if (!strcmp(argv[i], "-r") || !strcmp(argv[i], "--redir-stdout")) 1028 fRedirStdOut = 1; 908 1029 else if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--verbose")) 909 1030 g_fVerbose = 1; … … 936 1057 * Do the compiling. 937 1058 */ 938 kObjCachePreCompile(pEntry, papszArgvPreComp, cArgvPreComp, pszPreCompName );1059 kObjCachePreCompile(pEntry, papszArgvPreComp, cArgvPreComp, pszPreCompName, fRedirStdOut); 939 1060 kObjCacheCompileIfNeeded(pEntry, papszArgvCompile, cArgvCompile, pszObjName); 940 1061 … … 948 1069 } 949 1070 950
Note:
See TracChangeset
for help on using the changeset viewer.