Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2078 lines
58 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1989 - 1994
  5. //
  6. // File: builddb.c
  7. //
  8. // Contents: Contains the file and directory database manipulation
  9. // functions.
  10. //
  11. // History: 16-May-94 SteveWo Created
  12. // ... see SLM logs
  13. // 26-Jul-94 LyleC Cleanup/Add Pass0 Support
  14. //
  15. //----------------------------------------------------------------------------
  16. #include "build.h"
  17. BOOL fAssertCleanTree = FALSE;
  18. typedef struct _FLAGSTRINGS {
  19. ULONG Mask;
  20. LPSTR pszName;
  21. } FLAGSTRINGS;
  22. FLAGSTRINGS DirFlags[] = {
  23. { DIRDB_SOURCES, "Sources" },
  24. { DIRDB_DIRS, "Dirs" },
  25. { DIRDB_MAKEFILE, "Makefile" },
  26. { DIRDB_MAKEFIL0, "Makefil0" },
  27. { DIRDB_TARGETFILE0, "Targetfile0" },
  28. { DIRDB_TARGETFILES, "Targetfiles" },
  29. { DIRDB_RESOURCE, "Resource" },
  30. { DIRDB_PASS0, "PassZero" },
  31. { DIRDB_SOURCES_SET, "SourcesSet" },
  32. { DIRDB_CHICAGO_INCLUDES, "ChicagoIncludes" },
  33. { DIRDB_NEW, "New" },
  34. { DIRDB_SCANNED, "Scanned" },
  35. { DIRDB_SHOWN, "Shown" },
  36. { DIRDB_GLOBAL_INCLUDES, "GlobalIncludes" },
  37. { DIRDB_SYNCHRONIZE_BLOCK, "SynchronizeBlock" },
  38. { DIRDB_SYNCHRONIZE_DRAIN, "SynchronizeDrain" },
  39. { DIRDB_COMPILENEEDED, "CompileNeeded" },
  40. { DIRDB_COMPILEERRORS, "CompileErrors" },
  41. { DIRDB_SOURCESREAD, "SourcesRead" },
  42. { DIRDB_DLLTARGET, "DllTarget" },
  43. { DIRDB_LINKNEEDED, "LinkNeeded" },
  44. { DIRDB_FORCELINK, "ForceLink" },
  45. { DIRDB_PASS0NEEDED, "Pass0Needed" },
  46. { DIRDB_MAKEFIL1, "Makefil1" },
  47. { DIRDB_CHECKED_ALT_DIR, "CheckedAltDir" },
  48. { 0, NULL },
  49. };
  50. FLAGSTRINGS FileFlags[] = {
  51. { FILEDB_SOURCE, "Source" },
  52. { FILEDB_DIR, "Dir" },
  53. { FILEDB_HEADER, "Header" },
  54. { FILEDB_ASM, "Asm" },
  55. { FILEDB_MASM, "Masm" },
  56. { FILEDB_RC, "Rc" },
  57. { FILEDB_C, "C" },
  58. { FILEDB_MIDL, "Midl" },
  59. { FILEDB_ASN, "Asn" },
  60. { FILEDB_JAVA, "Java" },
  61. { FILEDB_MOF, "ManagedObjectFormat" },
  62. { FILEDB_CSHARP, "C#"},
  63. { FILEDB_SCANNED, "Scanned" },
  64. { FILEDB_OBJECTS_LIST, "ObjectsList" },
  65. { FILEDB_FILE_MISSING, "FileMissing" },
  66. { FILEDB_MKTYPLIB, "MkTypeLib" },
  67. { FILEDB_MULTIPLEPASS, "MultiplePass" },
  68. { FILEDB_PASS0, "PassZero" },
  69. { 0, NULL },
  70. };
  71. FLAGSTRINGS IncludeFlags[] = {
  72. { INCLUDEDB_LOCAL, "Local" },
  73. { INCLUDEDB_POST_HDRSTOP, "PostHdrStop" },
  74. { INCLUDEDB_MISSING, "Missing" },
  75. { INCLUDEDB_GLOBAL, "Global" },
  76. { INCLUDEDB_SNAPPED, "Snapped" },
  77. { INCLUDEDB_CYCLEALLOC, "CycleAlloc" },
  78. { INCLUDEDB_CYCLEROOT, "CycleRoot" },
  79. { INCLUDEDB_CYCLEORPHAN, "CycleOrphan" },
  80. { 0, NULL },
  81. };
  82. FLAGSTRINGS SourceFlags[] = {
  83. { SOURCEDB_SOURCES_LIST, "SourcesList" },
  84. { SOURCEDB_FILE_MISSING, "FileMissing" },
  85. { SOURCEDB_PCH, "Pch" },
  86. { SOURCEDB_OUT_OF_DATE, "OutOfDate" },
  87. { SOURCEDB_COMPILE_NEEDED, "CompileNeeded" },
  88. { 0, NULL },
  89. };
  90. //
  91. // Function prototypes
  92. //
  93. VOID
  94. FreeFileDB(PFILEREC *FileDB);
  95. VOID
  96. PrintFlags(FILE *pf, ULONG Flags, FLAGSTRINGS *pfs);
  97. //+---------------------------------------------------------------------------
  98. //
  99. // Function: CheckSum
  100. //
  101. // Synopsis: Returns a checksum value for a string.
  102. //
  103. //----------------------------------------------------------------------------
  104. USHORT
  105. CheckSum(LPSTR psz)
  106. {
  107. USHORT sum = 0;
  108. while (*psz != '\0') {
  109. if (sum & 0x8000) {
  110. sum = ((sum << 1) | 1) + *psz++;
  111. }
  112. else {
  113. sum = (sum << 1) + *psz++;
  114. }
  115. }
  116. return(sum);
  117. }
  118. //+---------------------------------------------------------------------------
  119. //
  120. // Function: FindSourceDirDB
  121. //
  122. // Synopsis: Builds a path from the two given components and returns
  123. // a filled DIRREC structure from it.
  124. //
  125. // Arguments: [pszDir] -- Directory
  126. // [pszRelPath] -- Path relative to [pszDir]
  127. // [fTruncateFileName] -- Remove a filename from [pszRelPath]
  128. //
  129. // Returns: A filled DIRREC structure for the given directory.
  130. //
  131. // Notes: If the directory does not exist in the data base, then a
  132. // DIRREC structure will be returned with the DIRDB_NEW flag
  133. // set and no other data (i.e. the directory will not have
  134. // been scanned.)
  135. //
  136. //----------------------------------------------------------------------------
  137. DIRREC *
  138. FindSourceDirDB(
  139. LPSTR pszDir, // directory
  140. LPSTR pszRelPath, // relative path
  141. BOOL fTruncateFileName) // TRUE: drop last component of path
  142. {
  143. LPSTR pszFile;
  144. char path[DB_MAX_PATH_LENGTH];
  145. AssertPathString(pszDir);
  146. AssertPathString(pszRelPath);
  147. strcpy(path, pszDir);
  148. if (path[0] != '\0')
  149. strcat(path, "\\");
  150. strcat(path, pszRelPath);
  151. pszFile = path + strlen(path);
  152. if (fTruncateFileName) {
  153. while (pszFile > path) {
  154. pszFile--;
  155. if (*pszFile == '\\' || *pszFile == '/') {
  156. *pszFile = '\0';
  157. break;
  158. }
  159. }
  160. }
  161. if (!CanonicalizePathName(path, CANONICALIZE_ONLY, path)) {
  162. return(NULL);
  163. }
  164. if (DEBUG_4) {
  165. BuildMsgRaw(
  166. "FindSourceDirDB(%s, %s, %u)\n",
  167. path,
  168. pszFile,
  169. fTruncateFileName);
  170. }
  171. AssertPathString(path);
  172. return(LoadDirDB(path));
  173. }
  174. //+---------------------------------------------------------------------------
  175. //
  176. // Function: FindSourceFileDB
  177. //
  178. // Synopsis: Returns a FILEREC with information about the given file.
  179. //
  180. // Arguments: [pdr] -- DIRREC giving directory from which to start
  181. // looking for [pszRelPath]
  182. // [pszRelPath] -- Relative path from [pdr] of the file
  183. // [ppdr] -- [out] DIRREC of directory actually containing
  184. // the file. Can be NULL.
  185. //
  186. // Returns: FILEREC for file of interest.
  187. //
  188. // Notes: If the directory containing the file has not yet been scanned,
  189. // then it will be scanned using ScanDirectory().
  190. //
  191. //----------------------------------------------------------------------------
  192. FILEREC *
  193. FindSourceFileDB(
  194. DIRREC *pdr,
  195. LPSTR pszRelPath,
  196. DIRREC **ppdr)
  197. {
  198. LPSTR p, pszFile;
  199. AssertPathString(pszRelPath);
  200. if (strchr(pszRelPath, '\\') != NULL) {
  201. // There's a path component in this filename. Let's see where it points to.
  202. if ( (pszRelPath[0] == '\\') || /* Absolute from root or UNC Path */
  203. (pszRelPath[1] == ':' )) /* drive : path */
  204. {
  205. pdr = FindSourceDirDB("", pszRelPath, TRUE);
  206. } else {
  207. pdr = FindSourceDirDB(pdr->Name, pszRelPath, TRUE);
  208. }
  209. }
  210. if (ppdr != NULL) {
  211. *ppdr = pdr;
  212. }
  213. if (pdr == NULL ) {
  214. return(NULL);
  215. }
  216. pszFile = pszRelPath;
  217. for (p = pszFile; *p != '\0'; p++) {
  218. if (*p == '\\') {
  219. pszFile = p + 1;
  220. }
  221. }
  222. if (DEBUG_4) {
  223. BuildMsgRaw("FindSourceFileDB(%s, %s)\n", pdr->Name, pszFile);
  224. }
  225. //
  226. // Scan the directory containing the file if we haven't already.
  227. //
  228. if ((pdr->DirFlags & DIRDB_SCANNED) == 0) {
  229. if (DEBUG_1) {
  230. BuildMsgRaw(
  231. "FindSourceFileDB(%s, %s) Delayed scan\n",
  232. pdr->Name,
  233. pszFile);
  234. }
  235. pdr = ScanDirectory(pdr->Name);
  236. if (pdr == NULL) {
  237. return(NULL);
  238. }
  239. }
  240. return(LookupFileDB(pdr, pszFile));
  241. }
  242. //+---------------------------------------------------------------------------
  243. //
  244. // Function: InsertSourceDB
  245. //
  246. // Synopsis: Insert a file listed in SOURCES= into a list of SOURCEREC
  247. // structures.
  248. //
  249. // Arguments: [ppsrNext] -- Head of list of sources files to add to.
  250. // [pfr] -- File to be inserted.
  251. // [SubDirMask] -- Indicates what directory the file is in.
  252. // (Current, Parent, or a machine-specific dir)
  253. // [SrcFlags] -- SOURCEDB flags appropriate to this file.
  254. //
  255. // Returns: SOURCEREC that was inserted. May be ignored.
  256. //
  257. // Notes: InsertSourceDB maintains a sort order for PickFirst() based
  258. // first on the filename extension, then on the subdirectory
  259. // mask.
  260. //
  261. // Two exceptions to the alphabetic sort are:
  262. // - No extension sorts last.
  263. // - .rc extension sorts first.
  264. //
  265. // If the file is already in the list of sources then this
  266. // function just updates the flags and returns.
  267. //
  268. //----------------------------------------------------------------------------
  269. SOURCEREC *
  270. InsertSourceDB(
  271. SOURCEREC **ppsrNext,
  272. FILEREC *pfr,
  273. UCHAR SubDirMask,
  274. UCHAR SrcFlags)
  275. {
  276. SOURCEREC *psr;
  277. SOURCEREC **ppsrInsert;
  278. LPSTR pszext;
  279. BOOL fRC;
  280. AssertFile(pfr);
  281. ppsrInsert = NULL;
  282. pszext = strrchr(pfr->Name, '.');
  283. fRC = FALSE;
  284. if (pszext != NULL && _stricmp(pszext, ".rc") == 0) {
  285. fRC = TRUE;
  286. }
  287. for ( ; (psr = *ppsrNext) != NULL; ppsrNext = &psr->psrNext) {
  288. LPSTR p;
  289. int r;
  290. AssertSource(psr);
  291. if (psr->pfrSource == pfr) {
  292. assert(psr->SourceSubDirMask == SubDirMask);
  293. psr->SrcFlags = SrcFlags;
  294. return(psr);
  295. }
  296. if (ppsrInsert == NULL && pszext != NULL) {
  297. if ((p = strrchr(psr->pfrSource->Name, '.')) == NULL) {
  298. r = -1; // insert new file here
  299. }
  300. else {
  301. r = strcmp(pszext, p);
  302. if (r != 0) {
  303. if (fRC) {
  304. r = -1; // insert new RC file here
  305. }
  306. else if (strcmp(p, ".rc") == 0) {
  307. r = 1; // old RC file comes first
  308. }
  309. }
  310. }
  311. if (r < 0 || SubDirMask > psr->SourceSubDirMask) {
  312. ppsrInsert = ppsrNext;
  313. }
  314. }
  315. }
  316. AllocMem(sizeof(SOURCEREC), &psr, MT_SOURCEDB);
  317. memset(psr, 0, sizeof(*psr));
  318. SigCheck(psr->Sig = SIG_SOURCEREC);
  319. if (ppsrInsert != NULL) {
  320. ppsrNext = ppsrInsert;
  321. }
  322. psr->psrNext = *ppsrNext;
  323. *ppsrNext = psr;
  324. psr->pfrSource = pfr;
  325. pfr->FileFlags |= FILEDB_SOURCEREC_EXISTS;
  326. psr->SourceSubDirMask = SubDirMask;
  327. psr->SrcFlags = SrcFlags;
  328. return(psr);
  329. }
  330. //+---------------------------------------------------------------------------
  331. //
  332. // Function: FindSourceDB
  333. //
  334. // Synopsis: Finds the SOURCEREC in a list which corresponds to the given
  335. // FILEREC.
  336. //
  337. //----------------------------------------------------------------------------
  338. SOURCEREC *
  339. FindSourceDB(
  340. SOURCEREC *psr,
  341. FILEREC *pfr)
  342. {
  343. while (psr != NULL) {
  344. AssertSource(psr);
  345. if (psr->pfrSource == pfr) {
  346. return(psr);
  347. }
  348. psr = psr->psrNext;
  349. }
  350. return(NULL);
  351. }
  352. //+---------------------------------------------------------------------------
  353. //
  354. // Function: FreeSourceDB
  355. //
  356. // Synopsis: Frees a list of SOURCERECs
  357. //
  358. // Arguments: [ppsr] -- List to free
  359. //
  360. //----------------------------------------------------------------------------
  361. VOID
  362. FreeSourceDB(SOURCEREC **ppsr)
  363. {
  364. if (*ppsr != NULL) {
  365. SOURCEREC *psr;
  366. SOURCEREC *psrNext;
  367. psr = *ppsr;
  368. AssertSource(psr);
  369. psrNext = psr->psrNext;
  370. SigCheck(psr->Sig = 0);
  371. FreeMem(ppsr, MT_SOURCEDB);
  372. *ppsr = psrNext;
  373. }
  374. }
  375. //+---------------------------------------------------------------------------
  376. //
  377. // Function: FreeIncludeDB
  378. //
  379. //----------------------------------------------------------------------------
  380. VOID
  381. FreeIncludeDB(INCLUDEREC **ppir)
  382. {
  383. if (*ppir != NULL) {
  384. INCLUDEREC *pir;
  385. INCLUDEREC *pirNext;
  386. pir = *ppir;
  387. AssertInclude(pir);
  388. AssertCleanTree(pir, NULL); // Tree must be clean
  389. pirNext = pir->Next;
  390. SigCheck(pir->Sig = 0);
  391. FreeMem(ppir, MT_INCLUDEDB);
  392. *ppir = pirNext;
  393. }
  394. }
  395. //+---------------------------------------------------------------------------
  396. //
  397. // Function: FreeFileDB
  398. //
  399. //----------------------------------------------------------------------------
  400. VOID
  401. FreeFileDB(FILEREC **ppfr)
  402. {
  403. if (*ppfr != NULL) {
  404. FILEREC *pfr;
  405. FILEREC *pfrNext;
  406. pfr = *ppfr;
  407. AssertFile(pfr);
  408. UnsnapIncludeFiles(pfr, TRUE);
  409. while (pfr->IncludeFiles) {
  410. FreeIncludeDB(&pfr->IncludeFiles);
  411. }
  412. pfrNext = pfr->Next;
  413. SigCheck(pfr->Sig = 0);
  414. FreeMem(ppfr, MT_FILEDB);
  415. *ppfr = pfrNext;
  416. }
  417. }
  418. //+---------------------------------------------------------------------------
  419. //
  420. // Function: FreeDirDB
  421. //
  422. //----------------------------------------------------------------------------
  423. VOID
  424. FreeDirDB(DIRREC **ppdr)
  425. {
  426. if (*ppdr != NULL) {
  427. DIRREC *pdr;
  428. DIRREC *pdrNext;
  429. pdr = *ppdr;
  430. AssertDir(pdr);
  431. FreeDirData(pdr);
  432. while (pdr->Files) {
  433. FreeFileDB(&pdr->Files);
  434. }
  435. pdrNext = pdr->Next;
  436. SigCheck(pdr->Sig = 0);
  437. FreeMem(ppdr, MT_DIRDB);
  438. *ppdr = pdrNext;
  439. }
  440. }
  441. //+---------------------------------------------------------------------------
  442. //
  443. // Function: FreeAllDirs
  444. //
  445. //----------------------------------------------------------------------------
  446. VOID
  447. FreeAllDirs(VOID)
  448. {
  449. while (AllDirs != NULL) {
  450. FreeDirDB(&AllDirs);
  451. #if DBG
  452. if (fDebug & 8) {
  453. BuildMsgRaw("Freed one directory\n");
  454. PrintAllDirs();
  455. }
  456. #endif
  457. }
  458. }
  459. //+---------------------------------------------------------------------------
  460. //
  461. // Function: LookupDirDB
  462. //
  463. // Synopsis: Searches the database for a given directory.
  464. //
  465. // Arguments: [DirName] -- Directory to search for.
  466. //
  467. // Returns: DIRREC of the given directory. NULL if not found.
  468. //
  469. // Notes: If the directory is not in the database it will not be added.
  470. // Use LoadDirDB in this case.
  471. //
  472. //----------------------------------------------------------------------------
  473. PDIRREC
  474. LookupDirDB(
  475. LPSTR DirName
  476. )
  477. {
  478. PDIRREC *DirDBNext = &AllDirs;
  479. PDIRREC DirDB;
  480. USHORT sum;
  481. AssertPathString(DirName);
  482. sum = CheckSum(DirName);
  483. while (DirDB = *DirDBNext) {
  484. if (sum == DirDB->CheckSum && strcmp(DirName, DirDB->Name) == 0) {
  485. if (DirDB->FindCount == 0 && fForce) {
  486. FreeDirDB(DirDBNext);
  487. return(NULL);
  488. }
  489. DirDB->FindCount++;
  490. // Move to head of list to make next lookup faster
  491. // *DirDBNext = DirDB->Next;
  492. // DirDB->Next = AllDirs;
  493. // AllDirs = DirDB;
  494. return(DirDB);
  495. }
  496. DirDBNext = &DirDB->Next;
  497. }
  498. return(NULL);
  499. }
  500. //+---------------------------------------------------------------------------
  501. //
  502. // Function: LoadDirDB
  503. //
  504. // Synopsis: Searches the database for a directory name, and if not found
  505. // creates a new DIRREC entry in the database.
  506. //
  507. // Arguments: [DirName] -- Directory to search for.
  508. //
  509. // Returns: Filled in DIRREC structure for the given directory.
  510. //
  511. // Notes: The directory will not be scanned if it wasn't in the
  512. // database. Use ScanDirectory to scan the directory,
  513. // however, note that InsertSourceDB will automatically scan
  514. // the directory only when necessary.
  515. //
  516. //----------------------------------------------------------------------------
  517. PDIRREC
  518. LoadDirDB(
  519. LPSTR DirName
  520. )
  521. {
  522. UINT i;
  523. PDIRREC DirDB, *DirDBNext;
  524. LPSTR s;
  525. AssertPathString(DirName);
  526. if (DirDB = LookupDirDB(DirName)) {
  527. return(DirDB);
  528. }
  529. if (ProbeFile(NULL, DirName) == -1) {
  530. return( NULL );
  531. }
  532. DirDBNext = &AllDirs;
  533. while (DirDB = *DirDBNext) {
  534. DirDBNext = &DirDB->Next;
  535. }
  536. AllDirsModified = TRUE;
  537. AllocMem(sizeof(DIRREC) + strlen(DirName), &DirDB, MT_DIRDB);
  538. memset(DirDB, 0, sizeof(*DirDB));
  539. SigCheck(DirDB->Sig = SIG_DIRREC);
  540. DirDB->DirFlags = DIRDB_NEW;
  541. DirDB->FindCount = 1;
  542. CopyString(DirDB->Name, DirName, TRUE);
  543. DirDB->CheckSum = CheckSum(DirDB->Name);
  544. if (DEBUG_1) {
  545. BuildMsgRaw("LoadDirDB creating %s\n", DirDB->Name);
  546. }
  547. *DirDBNext = DirDB;
  548. return( DirDB );
  549. }
  550. //+---------------------------------------------------------------------------
  551. //
  552. // Debug helper functions to print parts of the database.
  553. //
  554. //----------------------------------------------------------------------------
  555. #if DBG
  556. VOID
  557. PrintAllDirs(VOID)
  558. {
  559. DIRREC **ppdr, *pdr;
  560. for (ppdr = &AllDirs; (pdr = *ppdr) != NULL; ppdr = &pdr->Next) {
  561. PrintDirDB(pdr, 1|2|4);
  562. }
  563. }
  564. #endif
  565. VOID
  566. PrintFlags(FILE *pf, ULONG Flags, FLAGSTRINGS *pfs)
  567. {
  568. LPSTR p = ",";
  569. while (pfs->pszName != NULL) {
  570. if (pfs->Mask & Flags) {
  571. fprintf(pf, "%s %s", p, pfs->pszName);
  572. p = "";
  573. }
  574. pfs++;
  575. }
  576. fprintf(pf, szNewLine);
  577. }
  578. BOOL
  579. PrintIncludes(FILE *pf, FILEREC *pfr, BOOL fTree)
  580. {
  581. INCLUDEREC *pir;
  582. BOOL fMatch = pfr->IncludeFilesTree == pfr->IncludeFiles;
  583. pir = fTree? pfr->IncludeFilesTree : pfr->IncludeFiles;
  584. while (pir != NULL) {
  585. LPSTR pszdir = "<No File Record>";
  586. char OpenQuote, CloseQuote;
  587. if (pir->IncFlags & INCLUDEDB_LOCAL) {
  588. OpenQuote = CloseQuote = '"';
  589. }
  590. else {
  591. OpenQuote = '<';
  592. CloseQuote = '>';
  593. }
  594. fprintf(
  595. pf,
  596. " %c#include %c%s%c",
  597. fMatch? ' ' : fTree? '+' : '-',
  598. OpenQuote,
  599. pir->Name,
  600. CloseQuote);
  601. if (pir->Version != 0) {
  602. fprintf(pf, " (v%d)", pir->Version);
  603. }
  604. if (pir->pfrCycleRoot != NULL) {
  605. fprintf(
  606. pf,
  607. " (root=%s\\%s)",
  608. pir->pfrCycleRoot->Dir->Name,
  609. pir->pfrCycleRoot->Name);
  610. }
  611. if (pir->pfrInclude != NULL) {
  612. if (pir->pfrInclude->Dir == pfr->Dir) {
  613. pszdir = ".";
  614. }
  615. else {
  616. pszdir = pir->pfrInclude->Dir->Name;
  617. }
  618. }
  619. fprintf(pf, " %s", pszdir);
  620. PrintFlags(pf, pir->IncFlags, IncludeFlags);
  621. if (pir->NextTree != pir->Next) {
  622. fMatch = FALSE;
  623. }
  624. pir = fTree? pir->NextTree : pir->Next;
  625. }
  626. return(fMatch);
  627. }
  628. VOID
  629. PrintSourceDBList(SOURCEREC *psr, int i)
  630. {
  631. TARGET_MACHINE_INFO *pMachine;
  632. pMachine = i < 0 ? TargetMachines[0] : PossibleTargetMachines[i];
  633. for ( ; psr != NULL; psr = psr->psrNext) {
  634. assert(
  635. (psr->SourceSubDirMask & ~TMIDIR_PARENT) == 0 ||
  636. pMachine->SourceSubDirMask ==
  637. (psr->SourceSubDirMask & ~TMIDIR_PARENT));
  638. BuildMsgRaw(
  639. " %s%s%s%s%s",
  640. (psr->SourceSubDirMask & TMIDIR_PARENT)? "..\\" : "",
  641. (psr->SourceSubDirMask & ~TMIDIR_PARENT)?
  642. pMachine->SourceDirectory : "",
  643. (psr->SourceSubDirMask & ~TMIDIR_PARENT)? "\\" : "",
  644. psr->pfrSource->Name,
  645. (psr->SrcFlags & SOURCEDB_PCH)?
  646. " (pch)" :
  647. (psr->SrcFlags & SOURCEDB_SOURCES_LIST) == 0?
  648. " (From exe list)" : "");
  649. PrintFlags(stderr, psr->SrcFlags, SourceFlags);
  650. }
  651. }
  652. VOID
  653. PrintFileDB(FILE *pf, FILEREC *pfr, int DetailLevel)
  654. {
  655. fprintf(pf, " File: %s", pfr->Name);
  656. if (pfr->FileFlags & FILEDB_DIR) {
  657. fprintf(pf, " (Sub-Directory)");
  658. }
  659. else
  660. if (pfr->FileFlags & (FILEDB_SOURCE | FILEDB_HEADER)) {
  661. LPSTR pszType = (pfr->FileFlags & FILEDB_SOURCE)? "Source" : "Header";
  662. if (pfr->FileFlags & FILEDB_ASM) {
  663. fprintf(pf, " (Assembler (CPP) %s File)", pszType);
  664. }
  665. else
  666. if (pfr->FileFlags & FILEDB_MASM) {
  667. fprintf(pf, " (Assembler (MASM) %s File)", pszType);
  668. }
  669. else
  670. if (pfr->FileFlags & FILEDB_RC) {
  671. fprintf(pf, " (Resource Compiler (RC) %s File)", pszType);
  672. }
  673. else
  674. if (pfr->FileFlags & FILEDB_MIDL) {
  675. fprintf(pf, " (MIDL %s File)", pszType);
  676. }
  677. else
  678. if (pfr->FileFlags & FILEDB_ASN) {
  679. fprintf(pf, " (ASN %s File)", pszType);
  680. }
  681. else
  682. if (pfr->FileFlags & FILEDB_MKTYPLIB) {
  683. fprintf(pf, " (Type Library (MkTypLib) %s File)", pszType);
  684. }
  685. else {
  686. fprintf(pf, " (C %s File)", pszType);
  687. }
  688. if ((pfr->FileFlags & FILEDB_HEADER) && pfr->Version != 0) {
  689. fprintf(pf, " (v%d)", pfr->Version);
  690. }
  691. if (pfr->GlobalSequence != 0) {
  692. fprintf(pf, " (GlobalSeq=%d)", pfr->GlobalSequence);
  693. }
  694. if (pfr->LocalSequence != 0) {
  695. fprintf(pf, " (LocalSeq=%d)", pfr->LocalSequence);
  696. }
  697. fprintf(pf, " - %u lines", pfr->SourceLines);
  698. }
  699. PrintFlags(pf, pfr->FileFlags, FileFlags);
  700. if (pfr->IncludeFiles != NULL) {
  701. BOOL fMatch;
  702. fMatch = PrintIncludes(pf, pfr, FALSE);
  703. if (pfr->IncludeFilesTree != NULL) {
  704. fprintf(pf, " IncludeTree %s\n", fMatch? "matches" : "differs:");
  705. if (!fMatch) {
  706. PrintIncludes(pf, pfr, TRUE);
  707. }
  708. }
  709. }
  710. }
  711. VOID
  712. PrintDirDB(DIRREC *pdr, int DetailLevel)
  713. {
  714. FILE *pf = stderr;
  715. FILEREC *pfr, **ppfr;
  716. if (DetailLevel & 1) {
  717. fprintf(pf, "Directory: %s", pdr->Name);
  718. if (pdr->DirFlags & DIRDB_DIRS) {
  719. fprintf(pf, " (Dirs Present)");
  720. }
  721. if (pdr->DirFlags & DIRDB_SOURCES) {
  722. fprintf(pf, " (Sources Present)");
  723. }
  724. if (pdr->DirFlags & DIRDB_MAKEFILE) {
  725. fprintf(pf, " (Makefile Present)");
  726. }
  727. PrintFlags(pf, pdr->DirFlags, DirFlags);
  728. }
  729. if (DetailLevel & 2) {
  730. if (pdr->TargetPath != NULL) {
  731. fprintf(pf, " TargetPath: %s\n", pdr->TargetPath);
  732. }
  733. if (pdr->TargetName != NULL) {
  734. fprintf(pf, " TargetName: %s\n", pdr->TargetName);
  735. }
  736. if (pdr->TargetExt != NULL) {
  737. fprintf(pf, " TargetExt: %s\n", pdr->TargetExt);
  738. }
  739. if (pdr->KernelTest != NULL) {
  740. fprintf(pf, " KernelTest: %s\n", pdr->KernelTest);
  741. }
  742. if (pdr->UserAppls != NULL) {
  743. fprintf(pf, " UserAppls: %s\n", pdr->UserAppls);
  744. }
  745. if (pdr->UserTests != NULL) {
  746. fprintf(pf, " UserTests: %s\n", pdr->UserTests);
  747. }
  748. if (pdr->PchObj != NULL) {
  749. fprintf(pf, " PchObj: %s\n", pdr->PchObj);
  750. }
  751. if (pdr->Pch != NULL) {
  752. fprintf(pf, " Pch: %s\n", pdr->Pch);
  753. }
  754. }
  755. if (DetailLevel & 4) {
  756. for (ppfr = &pdr->Files; (pfr = *ppfr) != NULL; ppfr = &pfr->Next) {
  757. PrintFileDB(pf, pfr, DetailLevel);
  758. }
  759. }
  760. }
  761. //+---------------------------------------------------------------------------
  762. //
  763. // Function: LookupFileDB
  764. //
  765. // Synopsis: Search the database for the given file.
  766. //
  767. // Arguments: [DirDB] -- Directory containing the file
  768. // [FileName] -- File to look for
  769. //
  770. // Returns: FILEREC of file if found, NULL if not.
  771. //
  772. // Notes: The file will not be added to the database if not already
  773. // there.
  774. //
  775. //----------------------------------------------------------------------------
  776. PFILEREC
  777. LookupFileDB(
  778. PDIRREC DirDB,
  779. LPSTR FileName
  780. )
  781. {
  782. PFILEREC FileDB, *FileDBNext;
  783. USHORT sum;
  784. AssertPathString(FileName);
  785. sum = CheckSum(FileName);
  786. if (DEBUG_4) {
  787. BuildMsgRaw("LookupFileDB(%s, %s) - ", DirDB->Name, FileName);
  788. }
  789. FileDBNext = &DirDB->Files;
  790. while (FileDB = *FileDBNext) {
  791. if (sum == FileDB->CheckSum && strcmp(FileName, FileDB->Name) == 0) {
  792. if (DEBUG_4) {
  793. BuildMsgRaw("success\n");
  794. }
  795. return(FileDB);
  796. }
  797. FileDBNext = &FileDB->Next;
  798. }
  799. if (DEBUG_4) {
  800. BuildMsgRaw("failure\n");
  801. }
  802. return(NULL);
  803. }
  804. //+---------------------------------------------------------------------------
  805. //
  806. // FILEDESC
  807. //
  808. // FileDesc is a table describing file names and patterns that we recognize
  809. // and handle specially. WARNING: This table is ordered so the patterns
  810. // at the front are necessarily more specific than those later on.
  811. //
  812. //----------------------------------------------------------------------------
  813. char szMakefile[] = "#";
  814. char szClang[] = "//";
  815. char szAsn[] = "--";
  816. char szMasm[] = ";";
  817. //
  818. // N.B. The first entry in the file descriptor list is an entry that is
  819. // optionally filled with the name of the target dirs file for the
  820. // first build target.
  821. //
  822. FILEDESC FileDesc[] =
  823. { { "/0dirs", szMakefile, FALSE, 0, DIRDB_DIRS },
  824. { "makefile", szMakefile, FALSE, 0, DIRDB_MAKEFILE },
  825. { "makefil0", szMakefile, FALSE, 0, DIRDB_MAKEFIL0 | DIRDB_PASS0 },
  826. { "makefil1", szMakefile, FALSE, 0, DIRDB_MAKEFIL1 },
  827. { "sources", szMakefile, FALSE, 0, DIRDB_SOURCES },
  828. { "dirs", szMakefile, FALSE, 0, DIRDB_DIRS },
  829. { "mydirs", szMakefile, FALSE, 0, DIRDB_DIRS },
  830. { "makefile.inc", szMakefile, FALSE, 0, 0 },
  831. { "common.ver", szClang, TRUE, FILEDB_HEADER, 0 },
  832. { ".rc", szClang, TRUE, FILEDB_SOURCE | FILEDB_RC, DIRDB_RESOURCE },
  833. { ".rc2", szClang, TRUE, FILEDB_SOURCE | FILEDB_RC, DIRDB_RESOURCE },
  834. { ".rcs", szClang, TRUE, FILEDB_SOURCE | FILEDB_RC, DIRDB_RESOURCE },
  835. { ".rcv", szClang, TRUE, FILEDB_SOURCE | FILEDB_RC, DIRDB_RESOURCE },
  836. { ".ver", szClang, TRUE, FILEDB_SOURCE | FILEDB_RC, DIRDB_RESOURCE },
  837. { ".c", szClang, TRUE, FILEDB_SOURCE | FILEDB_C, 0 },
  838. { ".cxx", szClang, TRUE, FILEDB_SOURCE | FILEDB_C, 0 },
  839. { ".cpp", szClang, TRUE, FILEDB_SOURCE | FILEDB_C, 0 },
  840. { ".f", szClang, TRUE, FILEDB_SOURCE, 0 },
  841. { ".p", szClang, TRUE, FILEDB_SOURCE, 0 },
  842. { ".s", szClang, TRUE, FILEDB_SOURCE | FILEDB_ASM, 0 },
  843. { ".asm", szMasm, TRUE, FILEDB_SOURCE | FILEDB_MASM, 0 },
  844. { ".mc", szMasm, TRUE, FILEDB_SOURCE | FILEDB_RC |
  845. FILEDB_PASS0, DIRDB_PASS0 },
  846. { ".idl", szClang, TRUE, FILEDB_SOURCE | FILEDB_MIDL |
  847. FILEDB_PASS0, DIRDB_PASS0 },
  848. { ".asn", szAsn, TRUE, FILEDB_SOURCE | FILEDB_ASN |
  849. FILEDB_MULTIPLEPASS | FILEDB_PASS0,
  850. DIRDB_PASS0 },
  851. { ".tdl", szClang, TRUE, FILEDB_SOURCE | FILEDB_MKTYPLIB | FILEDB_PASS0, 0 },
  852. { ".odl", szClang, TRUE, FILEDB_SOURCE | FILEDB_MKTYPLIB | FILEDB_PASS0, 0 },
  853. { ".pdl", szClang, TRUE, FILEDB_SOURCE | FILEDB_PASS0, 0 },
  854. { ".h", szClang, TRUE, FILEDB_HEADER | FILEDB_C, 0 },
  855. { ".hxx", szClang, TRUE, FILEDB_HEADER | FILEDB_C, 0 },
  856. { ".hpp", szClang, TRUE, FILEDB_HEADER | FILEDB_C, 0 },
  857. { ".hmd", szClang, TRUE, FILEDB_HEADER | FILEDB_C, 0 },
  858. { ".hdl", szClang, TRUE, FILEDB_HEADER | FILEDB_C, 0 },
  859. { ".inl", szClang, TRUE, FILEDB_HEADER | FILEDB_C, 0 },
  860. { ".rh", szClang, TRUE, FILEDB_HEADER | FILEDB_C, 0 },
  861. { ".dlg", szClang, TRUE, FILEDB_HEADER | FILEDB_RC, 0 },
  862. { ".inc", szMasm, TRUE, FILEDB_HEADER | FILEDB_MASM, 0 },
  863. { ".src", szClang, TRUE, FILEDB_HEADER | FILEDB_C, 0 }, // see mvdm\softpc.new\obj.vdm\imlibdep.c
  864. { ".def", szClang, TRUE, FILEDB_HEADER | FILEDB_C, 0 },
  865. { ".thk", szClang, TRUE, FILEDB_SOURCE | FILEDB_MULTIPLEPASS |
  866. FILEDB_PASS0, DIRDB_PASS0 },
  867. { ".java", szClang, TRUE, FILEDB_SOURCE | FILEDB_JAVA, 0 },
  868. { ".mof", szClang, TRUE, FILEDB_SOURCE | FILEDB_MOF |
  869. FILEDB_PASS0, DIRDB_PASS0 },
  870. { ".cs", szClang, TRUE, FILEDB_SOURCE | FILEDB_CSHARP, 0 },
  871. // MUST BE LAST
  872. { NULL, "", FALSE, 0, 0 }
  873. };
  874. //+---------------------------------------------------------------------------
  875. //
  876. // Function: MatchFileDesc
  877. //
  878. // Synopsis: Matches the given filename to an entry in FileDesc, if
  879. // possible.
  880. //
  881. // Arguments: [pszFile] -- File to match
  882. //
  883. // Returns: A FILEDESC structure. If a match was not found the data
  884. // in the FILEDESC will be empty.
  885. //
  886. //----------------------------------------------------------------------------
  887. FILEDESC *
  888. MatchFileDesc(LPSTR pszFile)
  889. {
  890. LPSTR pszExt = strrchr(pszFile, '.');
  891. FILEDESC *pfd;
  892. AssertPathString(pszFile);
  893. pfd = &FileDesc[0];
  894. while (pfd->pszPattern != NULL) {
  895. if (pfd->pszPattern[0] == '.') {
  896. if (pszExt != NULL && !strcmp(pszExt, pfd->pszPattern))
  897. break;
  898. }
  899. else
  900. if (!strcmp(pszFile, pfd->pszPattern))
  901. break;
  902. pfd++;
  903. }
  904. return pfd;
  905. }
  906. //+---------------------------------------------------------------------------
  907. //
  908. // Function: InsertFileDB
  909. //
  910. // Synopsis: Adds a file to the database.
  911. //
  912. // Arguments: [DirDB] -- Directory containing the file
  913. // [FileName] -- File to add
  914. // [DateTime] -- Timestamp of file
  915. // [Attr] -- File attributes (directory or file)
  916. // [FileFlags] -- FILEDB flags
  917. //
  918. // Returns: New FILEREC of file
  919. //
  920. //----------------------------------------------------------------------------
  921. PFILEREC
  922. InsertFileDB(
  923. PDIRREC DirDB,
  924. LPSTR FileName,
  925. ULONG DateTime,
  926. USHORT Attr,
  927. ULONG FileFlags)
  928. {
  929. PFILEREC FileDB, *FileDBNext;
  930. LPSTR pszCommentToEOL = NULL;
  931. AssertPathString(FileName);
  932. if (Attr & FILE_ATTRIBUTE_DIRECTORY) {
  933. if (!strcmp(FileName, ".")) {
  934. return(NULL);
  935. }
  936. if (!strcmp(FileName, "..")) {
  937. return(NULL);
  938. }
  939. assert(FileFlags == 0);
  940. FileFlags = FILEDB_DIR;
  941. }
  942. else {
  943. FILEDESC *pfd = MatchFileDesc(FileName);
  944. DirDB->DirFlags |= pfd->DirFlags;
  945. FileFlags |= pfd->FileFlags;
  946. if (!pfd->fNeedFileRec) {
  947. return (NULL);
  948. }
  949. pszCommentToEOL = pfd->pszCommentToEOL;
  950. }
  951. FileDBNext = &DirDB->Files;
  952. while ((FileDB = *FileDBNext) != NULL) {
  953. FileDBNext = &(*FileDBNext)->Next;
  954. if (strcmp(FileName, FileDB->Name) == 0) {
  955. BuildError(
  956. "%s: ignoring second instance of %s\n",
  957. DirDB->Name,
  958. FileName);
  959. return(NULL);
  960. }
  961. }
  962. AllocMem(sizeof(FILEREC) + strlen(FileName), &FileDB, MT_FILEDB);
  963. memset(FileDB, 0, sizeof(*FileDB));
  964. SigCheck(FileDB->Sig = SIG_FILEREC);
  965. CopyString(FileDB->Name, FileName, TRUE);
  966. FileDB->CheckSum = CheckSum(FileDB->Name);
  967. FileDB->DateTime = DateTime;
  968. FileDB->Attr = Attr;
  969. FileDB->Dir = DirDB;
  970. FileDB->FileFlags = FileFlags;
  971. FileDB->NewestDependency = FileDB;
  972. FileDB->pszCommentToEOL = pszCommentToEOL;
  973. if ((FileFlags & FILEDB_FILE_MISSING) == 0) {
  974. AllDirsModified = TRUE;
  975. }
  976. *FileDBNext = FileDB;
  977. return(FileDB);
  978. }
  979. //+---------------------------------------------------------------------------
  980. //
  981. // Function: DeleteUnscannedFiles
  982. //
  983. // Synopsis: Removes unscanned files (leaving scanned files and directories)
  984. // from the Files list of the given directory
  985. //
  986. // Arguments: [DirDB] -- Directory to clean up
  987. //
  988. //----------------------------------------------------------------------------
  989. VOID
  990. DeleteUnscannedFiles(
  991. PDIRREC DirDB
  992. )
  993. {
  994. PFILEREC FileDB, *FileDBNext;
  995. FileDBNext = &DirDB->Files;
  996. while (FileDB = *FileDBNext) {
  997. //
  998. // If a file has the missing flag set then it doesn't exist. But for
  999. // it to be in the list of files it has to be listed in a SOURCES line
  1000. // (or some equivalent). This means there is a SOURCEREC somewhere
  1001. // which is pointing to the FILEREC for that file, so we don't want to
  1002. // free its memory.
  1003. //
  1004. if ( (FileDB->FileFlags & (FILEDB_SCANNED | FILEDB_FILE_MISSING | FILEDB_SOURCEREC_EXISTS)) ||
  1005. (FileDB->Attr & FILE_ATTRIBUTE_DIRECTORY) ) {
  1006. FileDBNext = &FileDB->Next;
  1007. }
  1008. else {
  1009. FreeFileDB( FileDBNext );
  1010. AllDirsModified = TRUE;
  1011. }
  1012. }
  1013. }
  1014. //+---------------------------------------------------------------------------
  1015. //
  1016. // Function: InsertIncludeDB
  1017. //
  1018. // Synopsis: Inserts an include file into the database
  1019. //
  1020. // Arguments: [FileDB] -- File which includes this file
  1021. // [IncludeFileName] -- Name of include file
  1022. // [IncFlags] -- INCLUDEDB flags for this file
  1023. //
  1024. // Returns: INCLUDEREC of previously existing or new entry one.
  1025. //
  1026. //----------------------------------------------------------------------------
  1027. PINCLUDEREC
  1028. InsertIncludeDB(
  1029. PFILEREC FileDB,
  1030. LPSTR IncludeFileName,
  1031. USHORT IncFlags
  1032. )
  1033. {
  1034. PINCLUDEREC IncludeDB, *IncludeDBNext;
  1035. AssertPathString(IncludeFileName);
  1036. IncludeDBNext = &FileDB->IncludeFiles;
  1037. while (IncludeDB = *IncludeDBNext) {
  1038. AssertCleanTree(IncludeDB, FileDB); // Tree must be clean
  1039. if (!strcmp(IncludeDB->Name, IncludeFileName)) {
  1040. IncludeDB->IncFlags &= ~INCLUDEDB_GLOBAL;
  1041. IncludeDB->pfrInclude = NULL;
  1042. return(IncludeDB);
  1043. }
  1044. IncludeDBNext = &IncludeDB->Next;
  1045. }
  1046. AllocMem(
  1047. sizeof(INCLUDEREC) + strlen(IncludeFileName),
  1048. IncludeDBNext,
  1049. MT_INCLUDEDB);
  1050. IncludeDB = *IncludeDBNext;
  1051. memset(IncludeDB, 0, sizeof(*IncludeDB));
  1052. SigCheck(IncludeDB->Sig = SIG_INCLUDEREC);
  1053. IncludeDB->IncFlags = IncFlags;
  1054. CopyString(IncludeDB->Name, IncludeFileName, TRUE);
  1055. AllDirsModified = TRUE;
  1056. return(IncludeDB);
  1057. }
  1058. //+---------------------------------------------------------------------------
  1059. //
  1060. // Function: LinkToCycleRoot
  1061. //
  1062. //----------------------------------------------------------------------------
  1063. VOID
  1064. LinkToCycleRoot(INCLUDEREC *pirOrg, FILEREC *pfrCycleRoot)
  1065. {
  1066. INCLUDEREC *pir;
  1067. AllocMem(
  1068. sizeof(INCLUDEREC) + strlen(pfrCycleRoot->Name),
  1069. &pir,
  1070. MT_INCLUDEDB);
  1071. memset(pir, 0, sizeof(*pir));
  1072. SigCheck(pir->Sig = SIG_INCLUDEREC);
  1073. pir->IncFlags = INCLUDEDB_SNAPPED | INCLUDEDB_CYCLEALLOC;
  1074. pir->pfrInclude = pfrCycleRoot;
  1075. CopyString(pir->Name, pfrCycleRoot->Name, TRUE);
  1076. if (DEBUG_1) {
  1077. BuildMsgRaw(
  1078. "%x CycleAlloc %s\\%s <- %s\\%s\n",
  1079. pir,
  1080. pir->pfrInclude->Dir->Name,
  1081. pir->pfrInclude->Name,
  1082. pirOrg->pfrInclude->Dir->Name,
  1083. pirOrg->pfrInclude->Name);
  1084. }
  1085. MergeIncludeFiles(pirOrg->pfrInclude, pir, NULL);
  1086. assert((pir->IncFlags & INCLUDEDB_CYCLEORPHAN) == 0);
  1087. assert(pir->IncFlags & INCLUDEDB_CYCLEROOT);
  1088. }
  1089. //+---------------------------------------------------------------------------
  1090. //
  1091. // Function: MergeIncludeFiles
  1092. //
  1093. //----------------------------------------------------------------------------
  1094. VOID
  1095. MergeIncludeFiles(FILEREC *pfr, INCLUDEREC *pirList, FILEREC *pfrRoot)
  1096. {
  1097. INCLUDEREC *pirT;
  1098. INCLUDEREC *pir, **ppir;
  1099. while ((pirT = pirList) != NULL) {
  1100. pirList = pirList->NextTree;
  1101. pirT->NextTree = NULL;
  1102. assert(pirT->pfrInclude != NULL);
  1103. for (ppir = &pfr->IncludeFilesTree;
  1104. (pir = *ppir) != NULL;
  1105. ppir = &pir->NextTree) {
  1106. if (pirT->pfrInclude == pir->pfrInclude) {
  1107. if (pirT->IncFlags & INCLUDEDB_CYCLEROOT) {
  1108. RemoveFromCycleRoot(pirT, pfrRoot);
  1109. }
  1110. pirT->IncFlags |= INCLUDEDB_CYCLEORPHAN;
  1111. if (DEBUG_1) {
  1112. BuildMsgRaw(
  1113. "%x CycleOrphan %s\\%s <- %s\\%s\n",
  1114. pirT,
  1115. pirT->pfrInclude->Dir->Name,
  1116. pirT->pfrInclude->Name,
  1117. pfr->Dir->Name,
  1118. pfr->Name);
  1119. }
  1120. break;
  1121. }
  1122. }
  1123. if (*ppir == NULL) {
  1124. *ppir = pirT;
  1125. pirT->pfrCycleRoot = pfr;
  1126. pirT->IncFlags |= INCLUDEDB_CYCLEROOT;
  1127. if (DEBUG_1) {
  1128. BuildMsgRaw(
  1129. "%x CycleRoot %s\\%s <- %s\\%s\n",
  1130. pirT,
  1131. pirT->pfrInclude->Dir->Name,
  1132. pirT->pfrInclude->Name,
  1133. pirT->pfrCycleRoot->Dir->Name,
  1134. pirT->pfrCycleRoot->Name);
  1135. }
  1136. }
  1137. }
  1138. if (fDebug & 16) {
  1139. PrintFileDB(stderr, pfr, 2);
  1140. }
  1141. }
  1142. //+---------------------------------------------------------------------------
  1143. //
  1144. // Function: RemoveFromCycleRoot
  1145. //
  1146. //----------------------------------------------------------------------------
  1147. VOID
  1148. RemoveFromCycleRoot(INCLUDEREC *pir, FILEREC *pfrRoot)
  1149. {
  1150. INCLUDEREC **ppir;
  1151. assert(pir->pfrCycleRoot != NULL);
  1152. // if pfrRoot was passed in, the caller knows it's on pfrRoot's list,
  1153. // and is already dealing with the linked list without our help.
  1154. if (pfrRoot != NULL) {
  1155. assert((pir->IncFlags & INCLUDEDB_CYCLEALLOC) == 0);
  1156. assert(pir->pfrCycleRoot == pfrRoot);
  1157. pir->pfrCycleRoot = NULL;
  1158. pir->IncFlags &= ~INCLUDEDB_CYCLEROOT;
  1159. if (DEBUG_1) {
  1160. BuildMsgRaw(
  1161. "%x CycleUnroot %s\\%s <- %s\\%s\n",
  1162. pir,
  1163. pir->pfrInclude->Dir->Name,
  1164. pir->pfrInclude->Name,
  1165. pfrRoot->Dir->Name,
  1166. pfrRoot->Name);
  1167. }
  1168. return;
  1169. }
  1170. ppir = &pir->pfrCycleRoot->IncludeFilesTree;
  1171. while (*ppir != NULL) {
  1172. if (*ppir == pir) {
  1173. *ppir = pir->NextTree; // remove from tree list
  1174. pir->NextTree = NULL;
  1175. pir->pfrCycleRoot = NULL;
  1176. pir->IncFlags &= ~INCLUDEDB_CYCLEROOT;
  1177. return;
  1178. }
  1179. ppir = &(*ppir)->NextTree;
  1180. }
  1181. BuildError(
  1182. "%s\\%s: %x %s: not on cycle root's list\n",
  1183. pir->pfrCycleRoot->Dir->Name,
  1184. pir->pfrCycleRoot->Name,
  1185. pir,
  1186. pir->Name);
  1187. assert(pir->pfrCycleRoot == NULL); // always asserts if loop exhausted
  1188. }
  1189. //+---------------------------------------------------------------------------
  1190. //
  1191. // Function: UnsnapIncludeFiles
  1192. //
  1193. // Synopsis: Removes pointers from INCLUDEREC to the actual FILEREC of
  1194. // the include file so we can 'resnap' them.
  1195. //
  1196. // Arguments: [pfr] -- FILEREC to unsnap
  1197. // [fUnsnapGlobal] -- If TRUE, global and local includes are
  1198. // unsnapped. Otherwise, just local ones are.
  1199. //
  1200. //----------------------------------------------------------------------------
  1201. VOID
  1202. UnsnapIncludeFiles(FILEREC *pfr, BOOL fUnsnapGlobal)
  1203. {
  1204. INCLUDEREC **ppir;
  1205. INCLUDEREC *pir;
  1206. // Dynamic Tree List:
  1207. // - no cycle orphans
  1208. // - cycle roots must belong to current file record
  1209. // - cycle allocs must be freed
  1210. AssertFile(pfr);
  1211. while (pfr->IncludeFilesTree != NULL) {
  1212. pir = pfr->IncludeFilesTree; // pick up next entry
  1213. AssertInclude(pir);
  1214. pfr->IncludeFilesTree = pir->NextTree; // remove from tree list
  1215. assert((pir->IncFlags & INCLUDEDB_CYCLEORPHAN) == 0);
  1216. if (pir->IncFlags & (INCLUDEDB_CYCLEROOT | INCLUDEDB_CYCLEALLOC)) {
  1217. // unsnap the record
  1218. pir->IncFlags &= ~(INCLUDEDB_SNAPPED | INCLUDEDB_GLOBAL);
  1219. pir->pfrInclude = NULL;
  1220. pir->NextTree = NULL;
  1221. }
  1222. if (pir->IncFlags & INCLUDEDB_CYCLEROOT) {
  1223. assert(pir->pfrCycleRoot == pfr);
  1224. pir->pfrCycleRoot = NULL;
  1225. pir->IncFlags &= ~INCLUDEDB_CYCLEROOT;
  1226. }
  1227. assert(pir->pfrCycleRoot == NULL);
  1228. if (pir->IncFlags & INCLUDEDB_CYCLEALLOC) {
  1229. pir->IncFlags &= ~INCLUDEDB_CYCLEALLOC;
  1230. assert(pir->Next == NULL);
  1231. FreeIncludeDB(&pir);
  1232. }
  1233. }
  1234. // Static List:
  1235. // - no cycle allocs
  1236. // - cycle roots must be removed from a different file's Dynamic list
  1237. // - cycle orphans are nops
  1238. for (ppir = &pfr->IncludeFiles; (pir = *ppir) != NULL; ppir = &pir->Next) {
  1239. assert((pir->IncFlags & INCLUDEDB_CYCLEALLOC) == 0);
  1240. if (pir->IncFlags & INCLUDEDB_CYCLEROOT) {
  1241. assert(pir->pfrCycleRoot != pfr);
  1242. RemoveFromCycleRoot(pir, NULL);
  1243. }
  1244. pir->IncFlags &= ~INCLUDEDB_CYCLEORPHAN;
  1245. if (pir->pfrInclude != NULL &&
  1246. (fUnsnapGlobal ||
  1247. (pir->pfrInclude->Dir->DirFlags & DIRDB_GLOBAL_INCLUDES) == 0)) {
  1248. // unsnap the record
  1249. pir->IncFlags &= ~(INCLUDEDB_SNAPPED | INCLUDEDB_GLOBAL);
  1250. pir->pfrInclude = NULL;
  1251. }
  1252. pir->NextTree = NULL;
  1253. }
  1254. }
  1255. #if DBG
  1256. //+---------------------------------------------------------------------------
  1257. //
  1258. // Function: AssertCleanTree
  1259. //
  1260. // Synopsis: Enforce that no include files are snapped.
  1261. //
  1262. // Arguments: [pir] - include record to test
  1263. // [pfr] - optional containing file record
  1264. //
  1265. //----------------------------------------------------------------------------
  1266. VOID
  1267. AssertCleanTree(INCLUDEREC *pir, OPTIONAL FILEREC *pfr)
  1268. {
  1269. if (IsCleanTree(pir)) {
  1270. return;
  1271. }
  1272. if (fAssertCleanTree) {
  1273. BuildMsgRaw("\n*************************************\n");
  1274. BuildMsgRaw("Persistent Cycle: pir=%x: %s\n", pir, pir->Name);
  1275. if (pfr != NULL) {
  1276. BuildMsgRaw(" pfr=%x: %s\n", pfr, pfr->Name);
  1277. if (pfr->Dir != NULL) {
  1278. BuildMsgRaw(" pdr=%x: %s\n", pfr->Dir, pfr->Dir->Name);
  1279. }
  1280. }
  1281. if (pir->pfrInclude != NULL) {
  1282. BuildMsgRaw(" pfrInclude=%x: %s\n", pir->pfrInclude, pir->pfrInclude->Name);
  1283. if (pir->pfrInclude->Dir != NULL) {
  1284. BuildMsgRaw(" pdrInclude=%x: %s\n", pir->pfrInclude->Dir, pir->pfrInclude->Dir->Name);
  1285. }
  1286. }
  1287. BuildMsgRaw("\n*************************************\n");
  1288. fflush(stdout);
  1289. fflush(stderr);
  1290. PrintAllDirs();
  1291. BuildMsgRaw("\n*************************************\n");
  1292. fflush(stdout);
  1293. fflush(stderr);
  1294. }
  1295. assert(IsCleanTree(pir));
  1296. }
  1297. #endif
  1298. //+---------------------------------------------------------------------------
  1299. //
  1300. // Function: UnsnapAllDirectories
  1301. //
  1302. // Synopsis: Removes pointers from all INCLUDERECs to the actual FILERECs
  1303. // of include files so we can 'resnap' them.
  1304. //
  1305. // Arguments: None
  1306. //----------------------------------------------------------------------------
  1307. VOID
  1308. UnsnapAllDirectories(VOID)
  1309. {
  1310. DIRREC *pdr;
  1311. UINT i;
  1312. GlobalSequence = LocalSequence = 0;
  1313. for (pdr = AllDirs; pdr != NULL; pdr = pdr->Next) {
  1314. FILEREC *pfr;
  1315. AssertDir(pdr);
  1316. // Clear unwanted flags on each directory
  1317. pdr->DirFlags &= ~(DIRDB_SCANNED |
  1318. DIRDB_PASS0NEEDED |
  1319. DIRDB_COMPILENEEDED |
  1320. DIRDB_NEW);
  1321. pdr->CountOfFilesToCompile = 0;
  1322. pdr->SourceLinesToCompile = 0;
  1323. pdr->CountOfPassZeroFiles = 0;
  1324. pdr->PassZeroLines = 0;
  1325. // Free all source records that point to missing files, because the
  1326. // file records may be freed when rescanning directories after pass 0.
  1327. if (pdr->pds != NULL)
  1328. {
  1329. for (i = 0; i < MAX_TARGET_MACHINES + 1; i++) {
  1330. SOURCEREC **ppsr;
  1331. SOURCEREC *psr;
  1332. ppsr = &pdr->pds->psrSourcesList[i];
  1333. while ((psr = *ppsr) != NULL)
  1334. {
  1335. if (psr->SrcFlags & SOURCEDB_FILE_MISSING)
  1336. {
  1337. FreeSourceDB(ppsr);
  1338. }
  1339. else
  1340. {
  1341. ppsr = &psr->psrNext;
  1342. }
  1343. }
  1344. }
  1345. }
  1346. // Clear out all snapped include files and sequence numbers
  1347. for (pfr = pdr->Files; pfr != NULL; pfr = pfr->Next) {
  1348. AssertFile(pfr);
  1349. UnsnapIncludeFiles(pfr, TRUE);
  1350. pfr->GlobalSequence = pfr->LocalSequence = 0;
  1351. }
  1352. }
  1353. }
  1354. //+---------------------------------------------------------------------------
  1355. //
  1356. // Function: MarkIncludeFileRecords
  1357. //
  1358. //----------------------------------------------------------------------------
  1359. VOID
  1360. MarkIncludeFileRecords(
  1361. PFILEREC FileDB
  1362. )
  1363. {
  1364. PINCLUDEREC IncludeDB, *IncludeDBNext;
  1365. IncludeDBNext = &FileDB->IncludeFiles;
  1366. while (IncludeDB = *IncludeDBNext) {
  1367. AssertCleanTree(IncludeDB, FileDB); // Tree must be clean
  1368. IncludeDB->pfrInclude = (PFILEREC) -1;
  1369. IncludeDBNext = &IncludeDB->Next;
  1370. }
  1371. }
  1372. //+---------------------------------------------------------------------------
  1373. //
  1374. // Function: DeleteIncludeFileRecords
  1375. //
  1376. //----------------------------------------------------------------------------
  1377. VOID
  1378. DeleteIncludeFileRecords(
  1379. PFILEREC FileDB
  1380. )
  1381. {
  1382. PINCLUDEREC IncludeDB, *IncludeDBNext;
  1383. IncludeDBNext = &FileDB->IncludeFiles;
  1384. while (IncludeDB = *IncludeDBNext) {
  1385. AssertCleanTree(IncludeDB, FileDB); // Tree must be clean
  1386. if (IncludeDB->pfrInclude == (PFILEREC) -1) {
  1387. FreeIncludeDB(IncludeDBNext);
  1388. }
  1389. else {
  1390. IncludeDBNext = &IncludeDB->Next;
  1391. }
  1392. }
  1393. }
  1394. //+---------------------------------------------------------------------------
  1395. //
  1396. // Function: FindIncludeFileDB
  1397. //
  1398. // Synopsis: Find the FILEREC for an include file that our compiland
  1399. // includes.
  1400. //
  1401. // Arguments: [pfrSource] -- FILEREC of file which includes the one
  1402. // we're looking for. Might be a header.
  1403. // [pfrCompiland] -- FILEREC of ultimate source file.
  1404. // [pdrBuild] -- DIRREC of directory being built
  1405. // [pszSourceDirectory] -- Name of machine-specific dir
  1406. // [IncludeDB] -- INCLUDEDB of include file we're looking
  1407. // for.
  1408. //
  1409. // Returns: FILEREC of include file, if found.
  1410. //
  1411. //----------------------------------------------------------------------------
  1412. PFILEREC
  1413. FindIncludeFileDB(
  1414. FILEREC *pfrSource,
  1415. FILEREC *pfrCompiland,
  1416. DIRREC *pdrBuild,
  1417. LPSTR pszSourceDirectory,
  1418. INCLUDEREC *IncludeDB)
  1419. {
  1420. DIRREC *pdr;
  1421. DIRREC *pdrMachine;
  1422. FILEREC *pfr;
  1423. UINT n;
  1424. AssertFile(pfrSource);
  1425. AssertFile(pfrCompiland);
  1426. AssertDir(pfrSource->Dir);
  1427. AssertDir(pfrCompiland->Dir);
  1428. AssertDir(pdrBuild);
  1429. assert(pfrSource->Dir->FindCount >= 1);
  1430. assert(pfrCompiland->Dir->FindCount >= 1);
  1431. assert(pdrBuild->FindCount >= 1);
  1432. AssertInclude(IncludeDB);
  1433. // The rules for #include "foo.h" and #include <foo.h> are:
  1434. // - "foo.h" searches in the directory of the source file that has the
  1435. // #include statement first, then falls into the INCLUDES= directories
  1436. // - <foo.h> simply searches the INCLUDES= directories
  1437. //
  1438. // - since makefile.def *always* passes -I. -ITargetMachines[i] first,
  1439. // that has to be handled here as well.
  1440. //
  1441. // - deal with #include <sys\types> and #include "..\foo\bar.h" by
  1442. // scanning those directories, too.
  1443. n = CountIncludeDirs;
  1444. pdrMachine = FindSourceDirDB(pdrBuild->Name, pszSourceDirectory, FALSE);
  1445. // If local ("foo.h"), search the current file's directory, too.
  1446. // The compiler also will search the directory of each higher level
  1447. // file in the include hierarchy, but we won't get quite so fancy here.
  1448. // Just search the directory of the current file and of the compiland.
  1449. //
  1450. // Skip these directories if they match the current build directory or
  1451. // the machine subdirectory, because that's handled below.
  1452. if (IncludeDB->IncFlags & INCLUDEDB_LOCAL) {
  1453. if (pfrCompiland->Dir != pdrBuild &&
  1454. pfrCompiland->Dir != pdrMachine &&
  1455. pfrCompiland->Dir != pfrSource->Dir) {
  1456. AddIncludeDir(pfrCompiland->Dir, &n);
  1457. }
  1458. if (pfrSource->Dir != pdrBuild && pfrSource->Dir != pdrMachine) {
  1459. AddIncludeDir(pfrSource->Dir, &n);
  1460. }
  1461. }
  1462. // Search the current target machine subdirectory of the build directory
  1463. // -- as per makefile.def
  1464. if (pdrMachine != NULL) {
  1465. AddIncludeDir(pdrMachine, &n);
  1466. }
  1467. // Search the current build directory -- as per makefile.def.
  1468. AddIncludeDir(pdrBuild, &n);
  1469. while (n--) {
  1470. pdr = IncludeDirs[n];
  1471. if (pdr == NULL) {
  1472. continue;
  1473. }
  1474. AssertDir(pdr);
  1475. assert(pdr->FindCount >= 1);
  1476. pfr = FindSourceFileDB(pdr, IncludeDB->Name, NULL);
  1477. if (pfr != NULL) {
  1478. if (DEBUG_1) {
  1479. BuildMsgRaw(
  1480. "Found include file %s\\%s\n",
  1481. pfr->Dir->Name,
  1482. pfr->Name);
  1483. }
  1484. return(pfr);
  1485. }
  1486. }
  1487. return(NULL);
  1488. }
  1489. //+---------------------------------------------------------------------------
  1490. //
  1491. // Function: SaveMasterDB
  1492. //
  1493. // Synopsis: Save the database to disk in build.dat
  1494. //
  1495. // Arguments: (none)
  1496. //
  1497. // Returns: TRUE if successful
  1498. //
  1499. //----------------------------------------------------------------------------
  1500. BOOL
  1501. SaveMasterDB(VOID)
  1502. {
  1503. PDIRREC DirDB, *DirDBNext;
  1504. PFILEREC FileDB, *FileDBNext;
  1505. PINCLUDEREC IncludeDB, *IncludeDBNext;
  1506. FILE *fh;
  1507. if (!AllDirsModified) {
  1508. return(TRUE);
  1509. }
  1510. if (!(fh = fopen(DbMasterName, "wb"))) {
  1511. return( FALSE );
  1512. }
  1513. setvbuf(fh, NULL, _IOFBF, 0x7000);
  1514. BuildMsg("Saving %s...", DbMasterName);
  1515. AllDirsModified = FALSE;
  1516. DirDBNext = &AllDirs;
  1517. fprintf(fh, "V %x\r\n", BUILD_VERSION);
  1518. while (DirDB = *DirDBNext) {
  1519. fprintf(fh, "D \"%s\" %x\r\n", DirDB->Name, DirDB->DirFlags);
  1520. FileDBNext = &DirDB->Files;
  1521. while (FileDB = *FileDBNext) {
  1522. if ((FileDB->FileFlags & FILEDB_FILE_MISSING) == 0) {
  1523. fprintf(
  1524. fh,
  1525. " F \"%s\" %x %x %lx %u %u\r\n",
  1526. FileDB->Name,
  1527. FileDB->FileFlags,
  1528. FileDB->Attr,
  1529. FileDB->DateTime,
  1530. FileDB->SourceLines,
  1531. FileDB->Version);
  1532. }
  1533. IncludeDBNext = &FileDB->IncludeFiles;
  1534. while (IncludeDB = *IncludeDBNext) {
  1535. fprintf(
  1536. fh,
  1537. " I \"%s\" %x %u\r\n",
  1538. IncludeDB->Name,
  1539. IncludeDB->IncFlags,
  1540. IncludeDB->Version);
  1541. IncludeDBNext= &IncludeDB->Next;
  1542. }
  1543. FileDBNext = &FileDB->Next;
  1544. }
  1545. fprintf(fh, "\r\n");
  1546. DirDBNext = &DirDB->Next;
  1547. }
  1548. fclose(fh);
  1549. BuildMsgRaw(szNewLine);
  1550. return(TRUE);
  1551. }
  1552. //+---------------------------------------------------------------------------
  1553. //
  1554. // Function: LoadMasterDB
  1555. //
  1556. // Synopsis: Load the master database from build.dat
  1557. //
  1558. // Arguments: (none)
  1559. //
  1560. //----------------------------------------------------------------------------
  1561. void
  1562. LoadMasterDB( void )
  1563. {
  1564. PDIRREC DirDB, *DirDBNext;
  1565. PFILEREC FileDB, *FileDBNext;
  1566. PINCLUDEREC IncludeDB, *IncludeDBNext;
  1567. FILE *fh;
  1568. LPSTR s;
  1569. char ch, ch2;
  1570. BOOL fFirst = TRUE;
  1571. UINT Version;
  1572. LPSTR pszerr = NULL;
  1573. AllDirs = NULL;
  1574. AllDirsModified = FALSE;
  1575. AllDirsInitialized = FALSE;
  1576. if (!SetupReadFile("", DbMasterName, ";", &fh)) {
  1577. return;
  1578. }
  1579. BuildMsg("Loading %s...", DbMasterName);
  1580. DirDBNext = &AllDirs;
  1581. FileDBNext = NULL;
  1582. IncludeDBNext = NULL;
  1583. while ((s = ReadLine(fh)) != NULL) {
  1584. ch = *s++;
  1585. if (ch == '\0') {
  1586. continue; // skip empty lines
  1587. }
  1588. ch2 = *s++; // should be a blank
  1589. if (ch2 == '\0') {
  1590. pszerr = "missing field";
  1591. break; // fail on single character lines
  1592. }
  1593. if (fFirst) {
  1594. if (ch != 'V' || ch2 != ' ' || !AToX(&s, &Version)) {
  1595. pszerr = "bad version format";
  1596. break;
  1597. }
  1598. if (Version != BUILD_VERSION) {
  1599. break;
  1600. }
  1601. fFirst = FALSE;
  1602. continue;
  1603. }
  1604. if (ch2 != ' ') {
  1605. pszerr = "bad separator";
  1606. break;
  1607. }
  1608. if (ch == 'D') {
  1609. DirDB = LoadMasterDirDB(s);
  1610. if (DirDB == NULL) {
  1611. pszerr = "Directory error";
  1612. break;
  1613. }
  1614. *DirDBNext = DirDB;
  1615. DirDBNext = &DirDB->Next;
  1616. FileDBNext = &DirDB->Files;
  1617. IncludeDBNext = NULL;
  1618. }
  1619. else
  1620. if (ch == 'F' && FileDBNext != NULL) {
  1621. FileDB = LoadMasterFileDB(s);
  1622. if (FileDB == NULL) {
  1623. pszerr = "File error";
  1624. break;
  1625. }
  1626. *FileDBNext = FileDB;
  1627. FileDBNext = &FileDB->Next;
  1628. FileDB->Dir = DirDB;
  1629. IncludeDBNext = &FileDB->IncludeFiles;
  1630. }
  1631. else
  1632. if (ch == 'I' && IncludeDBNext != NULL) {
  1633. IncludeDB = LoadMasterIncludeDB(s);
  1634. if (IncludeDB == NULL) {
  1635. pszerr = "Include error";
  1636. break;
  1637. }
  1638. *IncludeDBNext = IncludeDB;
  1639. IncludeDBNext = &IncludeDB->Next;
  1640. }
  1641. else {
  1642. pszerr = "bad entry type";
  1643. break;
  1644. }
  1645. }
  1646. if (s != NULL) {
  1647. if (pszerr == NULL) {
  1648. BuildMsgRaw(" - old version - recomputing.\n");
  1649. } else {
  1650. BuildMsgRaw(szNewLine);
  1651. BuildError("corrupt database (%s)\n", pszerr);
  1652. }
  1653. FreeAllDirs();
  1654. }
  1655. else {
  1656. BuildMsgRaw(szNewLine);
  1657. AllDirsInitialized = TRUE;
  1658. }
  1659. CloseReadFile(NULL);
  1660. return;
  1661. }
  1662. //+---------------------------------------------------------------------------
  1663. //
  1664. // Function: LoadMasterDirDB
  1665. //
  1666. // Synopsis: Load a directory entry from build.dat
  1667. //
  1668. // Arguments: [s] -- line containing text from file.
  1669. //
  1670. // Returns: DIRRECT
  1671. //
  1672. //----------------------------------------------------------------------------
  1673. PDIRREC
  1674. LoadMasterDirDB(
  1675. LPSTR s
  1676. )
  1677. {
  1678. PDIRREC DirDB;
  1679. LPSTR DirName;
  1680. ULONG DirFlags;
  1681. if (*s == '"') {
  1682. s++;
  1683. DirName = s;
  1684. while (*s != '"') {
  1685. s++;
  1686. }
  1687. *s++ = '\0';
  1688. }
  1689. else
  1690. {
  1691. DirName = s;
  1692. while (*s > ' ') {
  1693. s++;
  1694. }
  1695. }
  1696. *s++ = '\0';
  1697. if (!AToX(&s, &DirFlags)) {
  1698. return(NULL);
  1699. }
  1700. AllocMem(sizeof(DIRREC) + strlen(DirName), &DirDB, MT_DIRDB);
  1701. memset(DirDB, 0, sizeof(*DirDB));
  1702. SigCheck(DirDB->Sig = SIG_DIRREC);
  1703. DirDB->DirFlags = DirFlags & DIRDB_DBPRESERVE;
  1704. CopyString(DirDB->Name, DirName, TRUE);
  1705. DirDB->CheckSum = CheckSum(DirDB->Name);
  1706. return( DirDB );
  1707. }
  1708. //+---------------------------------------------------------------------------
  1709. //
  1710. // Function: LoadMasterFileDB
  1711. //
  1712. // Synopsis: Load a file entry from build.dat
  1713. //
  1714. // Arguments: [s] -- line containing text from file
  1715. //
  1716. // Returns: FILEREC
  1717. //
  1718. //----------------------------------------------------------------------------
  1719. PFILEREC
  1720. LoadMasterFileDB(
  1721. LPSTR s
  1722. )
  1723. {
  1724. PFILEREC FileDB;
  1725. LPSTR FileName;
  1726. ULONG Version;
  1727. ULONG FileFlags;
  1728. ULONG Attr;
  1729. ULONG SourceLines;
  1730. ULONG DateTime;
  1731. FILEDESC *pfd;
  1732. if (*s == '"') {
  1733. s++;
  1734. FileName = s;
  1735. while (*s != '"') {
  1736. s++;
  1737. }
  1738. *s++ = '\0';
  1739. }
  1740. else
  1741. {
  1742. FileName = s;
  1743. while (*s > ' ') {
  1744. s++;
  1745. }
  1746. }
  1747. *s++ = '\0';
  1748. if (!AToX(&s, &FileFlags) ||
  1749. !AToX(&s, &Attr) ||
  1750. !AToX(&s, &DateTime) ||
  1751. !AToD(&s, &SourceLines) ||
  1752. !AToD(&s, &Version) ||
  1753. strchr(FileName, '/') != NULL ||
  1754. strchr(FileName, '\\') != NULL) {
  1755. return(NULL);
  1756. }
  1757. AllocMem(sizeof(FILEREC) + strlen(FileName), &FileDB, MT_FILEDB);
  1758. memset(FileDB, 0, sizeof(*FileDB));
  1759. SigCheck(FileDB->Sig = SIG_FILEREC);
  1760. CopyString(FileDB->Name, FileName, TRUE);
  1761. FileDB->CheckSum = CheckSum(FileDB->Name);
  1762. FileDB->FileFlags = FileFlags & FILEDB_DBPRESERVE;
  1763. FileDB->Attr = (USHORT) Attr;
  1764. FileDB->DateTime = DateTime;
  1765. FileDB->Version = (USHORT) Version;
  1766. FileDB->SourceLines = SourceLines;
  1767. FileDB->NewestDependency = FileDB;
  1768. pfd = MatchFileDesc(FileDB->Name);
  1769. FileDB->pszCommentToEOL = pfd->pszCommentToEOL;
  1770. return(FileDB);
  1771. }
  1772. //+---------------------------------------------------------------------------
  1773. //
  1774. // Function: LoadMasterIncludeDB
  1775. //
  1776. // Synopsis: Loads an include file entry from build.dat
  1777. //
  1778. // Arguments: [s] -- line containing text from file.
  1779. //
  1780. // Returns: INCLUDEREC
  1781. //
  1782. //----------------------------------------------------------------------------
  1783. PINCLUDEREC
  1784. LoadMasterIncludeDB(
  1785. LPSTR s
  1786. )
  1787. {
  1788. PINCLUDEREC IncludeDB;
  1789. LPSTR FileName;
  1790. ULONG Version;
  1791. ULONG IncFlags;
  1792. if (*s == '"') {
  1793. s++;
  1794. FileName = s;
  1795. while (*s != '"') {
  1796. s++;
  1797. }
  1798. *s++ = '\0';
  1799. }
  1800. else
  1801. {
  1802. FileName = s;
  1803. while (*s > ' ') {
  1804. s++;
  1805. }
  1806. }
  1807. *s++ = '\0';
  1808. if (!AToX(&s, &IncFlags) || !AToD(&s, &Version)) {
  1809. return(NULL);
  1810. }
  1811. AllocMem(
  1812. sizeof(INCLUDEREC) + strlen(FileName),
  1813. &IncludeDB,
  1814. MT_INCLUDEDB);
  1815. memset(IncludeDB, 0, sizeof(*IncludeDB));
  1816. SigCheck(IncludeDB->Sig = SIG_INCLUDEREC);
  1817. IncludeDB->IncFlags = (USHORT) (IncFlags & INCLUDEDB_DBPRESERVE);
  1818. IncludeDB->Version = (USHORT) Version;
  1819. CopyString(IncludeDB->Name, FileName, TRUE);
  1820. return(IncludeDB);
  1821. }