Leaked source code of windows server 2003
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.

2329 lines
75 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: buildsrc.c
  7. //
  8. // Contents: Functions used to process SOURCES and DIRS files
  9. //
  10. // History: 16-May-89 SteveWo Created
  11. // 26-Jul-94 LyleC Split out from buildmak.c
  12. // 05-Dec-00 sbonev See SD changelist 2317
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "build.h"
  16. //
  17. // Definitions used by the macro functions
  18. //
  19. #define LPAREN '('
  20. #define RPAREN ')'
  21. // Legal character for a macro name.
  22. #define MACRO_CHAR(ch) iscsym(ch)
  23. #define CMACROMAX 1000 // maximum unique macros per sources/dirs file
  24. typedef struct _MACRO {
  25. LPSTR pszValue;
  26. UCHAR szName[1];
  27. } MACRO;
  28. MACRO *apMacro[CMACROMAX];
  29. UINT cMacro = 0;
  30. LPSTR *ppCurrentDirsFileName;
  31. DWORD StartTime;
  32. DWORD DirectoryStartTime;
  33. #define SOURCES_TARGETNAME 0
  34. #define SOURCES_TARGETPATH 1
  35. #define SOURCES_TARGETPATHLIB 2
  36. #define SOURCES_TARGETTYPE 3
  37. #define SOURCES_TARGETEXT 4
  38. #define SOURCES_INCLUDES 5
  39. #define SOURCES_NTTEST 6
  40. #define SOURCES_UMTYPE 7
  41. #define SOURCES_UMTEST 8
  42. #define SOURCES_OPTIONAL_UMTEST 9
  43. #define SOURCES_UMAPPL 10
  44. #define SOURCES_UMAPPLEXT 11
  45. #define SOURCES_NTTARGETFILE0 12
  46. #define SOURCES_NTTARGETFILES 13
  47. #define SOURCES_PRECOMPILED_INCLUDE 14
  48. #define SOURCES_PRECOMPILED_PCH 15
  49. #define SOURCES_PRECOMPILED_OBJ 16
  50. #define SOURCES_PRECOMPILED_TARGET 17
  51. #define SOURCES_CHICAGO_PRODUCT 18
  52. #define SOURCES_CONDITIONAL_INCLUDES 19
  53. #define SOURCES_SYNCHRONIZE_BLOCK 20
  54. #define SOURCES_SYNCHRONIZE_DRAIN 21
  55. #define SOURCES_PASS0_SOURCEDIR 22
  56. #define SOURCES_PASS0_HEADERDIR 23
  57. #define SOURCES_PASS0_UUIDDIR 24
  58. #define SOURCES_PASS0_CLIENTDIR 25
  59. #define SOURCES_PASS0_SERVERDIR 26
  60. #define SOURCES_IDLTYPE 27
  61. #define SOURCES_SOURCES_OPTIONS 28
  62. #define SOURCES_MFC_INCLUDES 29
  63. #define SOURCES_SDK_LIB_DEST 30
  64. #define SOURCES_DDK_LIB_DEST 31
  65. #define SOURCES_SDK_INC_PATH 32
  66. #define SOURCES_CRT_INC_PATH 33
  67. #define SOURCES_OAK_INC_PATH 34
  68. #define SOURCES_DDK_INC_PATH 35
  69. #define SOURCES_WDM_INC_PATH 36
  70. #define SOURCES_PRIVATE_INC_PATH 37
  71. #define SOURCES_CHECKED_ALT_DIR 38
  72. #define SOURCES_PROJECT_NAME 39
  73. #define SOURCES_PASS0_PUBLISH 40
  74. #define SOURCES_USER_INCLUDES 41
  75. #define SOURCES_LAST_INCLUDES 42
  76. #define SOURCES_MIDL_UUIDDIR 43
  77. #define SOURCES_SYNCHRONIZE_PASS2_BLOCK 44
  78. #define SOURCES_SYNCHRONIZE_PASS2_DRAIN 45
  79. #define SOURCES_MANAGED_CODE 46
  80. #define SOURCES_SYNC_PRODUCES 47
  81. #define SOURCES_SYNC_CONSUMES 48
  82. #define SOURCES_MANAGED_VB 49
  83. #define SOURCES_PASS0_BINPLACE 50
  84. #define SOURCES_PASS1_LINK 51
  85. LPSTR RelevantSourcesMacros[] = {
  86. "TARGETNAME",
  87. "TARGETPATH",
  88. "TARGETPATHLIB",
  89. "TARGETTYPE",
  90. "TARGETEXT",
  91. "INCLUDES",
  92. "NTTEST",
  93. "UMTYPE",
  94. "UMTEST",
  95. "OPTIONAL_UMTEST",
  96. "UMAPPL",
  97. "UMAPPLEXT",
  98. "NTTARGETFILE0",
  99. "NTTARGETFILES",
  100. "PRECOMPILED_INCLUDE",
  101. "PRECOMPILED_PCH",
  102. "PRECOMPILED_OBJ",
  103. "PRECOMPILED_TARGET",
  104. "CHICAGO_PRODUCT",
  105. "CONDITIONAL_INCLUDES",
  106. "SYNCHRONIZE_BLOCK",
  107. "SYNCHRONIZE_DRAIN",
  108. "PASS0_SOURCEDIR",
  109. "PASS0_HEADERDIR",
  110. "PASS0_UUIDDIR",
  111. "PASS0_CLIENTDIR",
  112. "PASS0_SERVERDIR",
  113. "IDL_TYPE",
  114. "SOURCES_OPTIONS",
  115. "MFC_INCLUDES",
  116. "SDK_LIB_DEST",
  117. "DDK_LIB_DEST",
  118. "SDK_INC_PATH",
  119. "CRT_INC_PATH",
  120. "OAK_INC_PATH",
  121. "DDK_INC_PATH",
  122. "WDM_INC_PATH",
  123. "PRIVATE_INC_PATH",
  124. "CHECKED_ALT_DIR",
  125. "_PROJECT_",
  126. "PASS0_PUBLISH",
  127. "USER_INCLUDES",
  128. "LAST_INCLUDES",
  129. "MIDL_UUIDDIR",
  130. "SYNCHRONIZE_PASS2_BLOCK",
  131. "SYNCHRONIZE_PASS2_DRAIN",
  132. "MANAGED_CODE",
  133. "BUILD_PRODUCES",
  134. "BUILD_CONSUMES",
  135. "MANAGED_VB",
  136. "PASS0_BINPLACE",
  137. "PASS1_LINK",
  138. NULL
  139. };
  140. #define SOURCES_MAX (ARRAY_SIZE(RelevantSourcesMacros) - 1)
  141. VOID
  142. MarkDirNames(PDIRREC DirDB, LPSTR TextLine, BOOL Required);
  143. //+---------------------------------------------------------------------------
  144. //
  145. // Function: CompressBlanks
  146. //
  147. // Synopsis: Compress multiple blank characters out of macro value, in
  148. // place.
  149. //
  150. // Arguments: [psrc] -- String to compress
  151. //
  152. // Notes: Note that tabs, CRs, continuation lines (and their line
  153. // breaks) have already been replaced with blanks.
  154. //
  155. //----------------------------------------------------------------------------
  156. VOID
  157. CompressBlanks(LPSTR psrc)
  158. {
  159. LPSTR pdst = psrc;
  160. while (*psrc == ' ') {
  161. psrc++; // skip leading macro value blanks
  162. }
  163. while (*psrc != '\0') {
  164. if (*psrc == '#') { // stop at comment
  165. break;
  166. }
  167. if ((*pdst++ = *psrc++) == ' ') {
  168. while (*psrc == ' ') {
  169. psrc++; // skip multiple blanks
  170. }
  171. }
  172. }
  173. *pdst = '\0'; // terminate the compressed copy
  174. if (*--pdst == ' ') {
  175. *pdst = '\0'; // trim trailing macro value blanks
  176. }
  177. }
  178. //+---------------------------------------------------------------------------
  179. //
  180. // Function: GetBaseDir
  181. //
  182. // Synopsis: Return the value of BASEDIR, the base NT directory, if
  183. // appropriate.
  184. //
  185. // Arguments: [pname] -- path to split
  186. //
  187. //----------------------------------------------------------------------------
  188. LPSTR
  189. GetBaseDir(LPSTR pname)
  190. {
  191. if (_stricmp("BASEDIR", pname) == 0) {
  192. return (NtRoot);
  193. }
  194. return (NULL);
  195. }
  196. //+---------------------------------------------------------------------------
  197. //
  198. // Function: FindMacro
  199. //
  200. // Synopsis: Returns the value of a given macro by name.
  201. //
  202. // Arguments: [pszName] -- Name of macro who's value is desired.
  203. //
  204. // Returns: String containing the value of the macro
  205. //
  206. //----------------------------------------------------------------------------
  207. LPSTR
  208. FindMacro(LPSTR pszName)
  209. {
  210. MACRO **ppm;
  211. for (ppm = apMacro; ppm < &apMacro[cMacro]; ppm++) {
  212. if (_stricmp(pszName, (*ppm)->szName) == 0) {
  213. return ((*ppm)->pszValue);
  214. }
  215. }
  216. return (NULL);
  217. }
  218. //+---------------------------------------------------------------------------
  219. //
  220. // Function: SaveMacro
  221. //
  222. // Synopsis: Save the value of a macro
  223. //
  224. // Arguments: [pszName] -- Name of macro to save
  225. // [pszValue] -- Value of macro
  226. //
  227. // Notes: A new string must be allocated and initialized prior to
  228. // freeing the old string when updating a macro value.
  229. //
  230. //----------------------------------------------------------------------------
  231. VOID
  232. SaveMacro(LPSTR pszName, LPSTR pszValue)
  233. {
  234. MACRO **ppm;
  235. for (ppm = apMacro; ppm < &apMacro[cMacro]; ppm++) {
  236. if (_stricmp(pszName, (*ppm)->szName) == 0) {
  237. break;
  238. }
  239. }
  240. if (ppm == &apMacro[CMACROMAX]) {
  241. BuildError("Macro table full, ignoring: %s = %s\r\n", pszName, pszValue);
  242. return;
  243. }
  244. if (ppm == &apMacro[cMacro]) {
  245. cMacro++;
  246. AllocMem(sizeof(MACRO) + strlen(pszName), ppm, MT_MACRO);
  247. strcpy((*ppm)->szName, pszName);
  248. (*ppm)->pszValue = NULL;
  249. }
  250. MakeMacroString(&(*ppm)->pszValue, pszValue);
  251. if (DEBUG_1) {
  252. BuildMsg(
  253. "SaveMacro(%s = %s)\r\n",
  254. (*ppm)->szName,
  255. (*ppm)->pszValue == NULL? "NULL" : (*ppm)->pszValue);
  256. }
  257. if ((*ppm)->pszValue == NULL) {
  258. FreeMem(ppm, MT_MACRO);
  259. *ppm = apMacro[--cMacro];
  260. }
  261. }
  262. //+---------------------------------------------------------------------------
  263. //
  264. // Function: FreeMacros
  265. //
  266. // Synopsis: Free all macros
  267. //
  268. // Arguments: (none)
  269. //
  270. //----------------------------------------------------------------------------
  271. VOID
  272. FreeMacros(VOID)
  273. {
  274. MACRO **ppm;
  275. for (ppm = apMacro; ppm < &apMacro[cMacro]; ppm++) {
  276. FreeString(&(*ppm)->pszValue, MT_DIRSTRING);
  277. FreeMem(ppm, MT_MACRO);
  278. assert(*ppm == NULL);
  279. }
  280. cMacro = 0;
  281. }
  282. //+---------------------------------------------------------------------------
  283. //
  284. // Function: SplitMacro
  285. //
  286. // Synopsis: Take a string containing "MACRONAME = VALUE" and return
  287. // the target and value.
  288. //
  289. // Arguments: [pline] -- String to split and target return.
  290. //
  291. // Returns: Value of macro.
  292. //
  293. //----------------------------------------------------------------------------
  294. LPSTR
  295. SplitMacro(LPSTR *pszTarget)
  296. {
  297. LPSTR pvalue, p, pline;
  298. pvalue = NULL;
  299. pline = *pszTarget;
  300. // Quickly reject comments and ! directives.
  301. if (*pline == '#' || *pline == '!') {
  302. return NULL;
  303. }
  304. if ((p = strchr(pline, '=')) != NULL) {
  305. pvalue = p + 1; // point past old '='
  306. while (p > pline && p[-1] == ' ') {
  307. p--; // point to start of trailing blanks
  308. }
  309. // Check for missing target.
  310. if (p == pline) {
  311. return NULL;
  312. }
  313. *p = '\0'; // trim trailing blanks & '='
  314. // Perform macro substitution on target.
  315. *pszTarget = NULL;
  316. if (!MakeMacroString(pszTarget, pline)) {
  317. return NULL;
  318. }
  319. // Validate target name. If must be a non-empty string of
  320. // valid macro name characters.
  321. if (**pszTarget == 0) {
  322. FreeString(pszTarget, MT_DIRSTRING);
  323. return NULL;
  324. }
  325. for (p = *pszTarget; *p != 0; p++) {
  326. if (!MACRO_CHAR(*p)) {
  327. FreeString(pszTarget, MT_DIRSTRING);
  328. return NULL;
  329. }
  330. }
  331. CompressBlanks(pvalue);
  332. }
  333. return (pvalue);
  334. }
  335. //+---------------------------------------------------------------------------
  336. //
  337. // Function: SubstituteString
  338. //
  339. // Synopsis: Perform any macro substitution. This code was copied from the
  340. // nmake source.
  341. //
  342. // Arguments:
  343. //
  344. // Returns:
  345. //
  346. // Notes:
  347. //
  348. //----------------------------------------------------------------------------
  349. void
  350. SubstituteString(
  351. char **result,
  352. char **name,
  353. char **dest,
  354. char **end,
  355. char *source,
  356. unsigned *length
  357. )
  358. {
  359. #define ESCH '^'
  360. PVOID pReallocResult;
  361. char *oldString, *newString;
  362. char *pEq, *pPar, *t;
  363. char *s;
  364. unsigned i;
  365. ++*name;
  366. for (pEq = *name; *pEq && *pEq != '='; pEq++)
  367. if (*pEq == ESCH)
  368. pEq++;
  369. // Did we find the '=' sign?
  370. if (*pEq != '=')
  371. printf("Error1\n");
  372. // Did the user forget the initial string?
  373. if (pEq == *name)
  374. printf("Error2\n");
  375. for (pPar = pEq; *pPar && *pPar != ')'; pPar++)
  376. if (*pPar == ESCH)
  377. pPar++;
  378. if (*pPar != ')')
  379. printf("Error3\n");
  380. oldString = (char *)malloc((UINT)((pEq - *name) + 1));
  381. if (!oldString) {
  382. BuildError("(Fatal Error) Out Of Memory: SubstituteString()\r\n");
  383. exit(16);
  384. }
  385. for (s = oldString, t = *name; *t != '='; *s++ = *t++)
  386. if (*t == ESCH)
  387. ++t;
  388. *s = '\0';
  389. i = strlen(oldString);
  390. newString = (char *)malloc((UINT)(pPar - pEq));
  391. if (!newString) {
  392. BuildError("(Fatal Error) Out Of Memory: SubstituteString()\r\n");
  393. exit(16);
  394. }
  395. for (s = newString, t++; *t != ')'; *s++ = *t++)
  396. if (*t == ESCH)
  397. ++t;
  398. *s = '\0';
  399. *name = pPar + 1;
  400. while (*source) {
  401. if ((*source == *oldString) // check for match
  402. && !strncmp(source, oldString, i)) { // copy new in for
  403. for (s = newString; *s; *(*dest)++ = *s++) // old string
  404. if (*dest == *end) {
  405. pReallocResult = realloc(*result, *length+100);
  406. if (!pReallocResult) {
  407. BuildError("(Fatal Error) Out Of Memory: SubstituteString()\r\n");
  408. exit(16);
  409. }
  410. *result = pReallocResult;
  411. *dest = *result + *length;
  412. *length += 100;
  413. *end = *result + *length;
  414. }
  415. source += i;
  416. continue;
  417. }
  418. if (*dest == *end) {
  419. pReallocResult = realloc(*result, *length+100);
  420. if (!pReallocResult) {
  421. BuildError("(Fatal Error) Out Of Memory: SubstituteString()\r\n");
  422. exit(16);
  423. }
  424. *result = pReallocResult;
  425. *dest = *result + *length;
  426. *length += 100;
  427. *end = *result + *length;
  428. }
  429. *(*dest)++ = *source++; // else copy 1 char
  430. }
  431. free(oldString);
  432. free(newString);
  433. }
  434. //+---------------------------------------------------------------------------
  435. //
  436. // Function: MakeMacroString
  437. //
  438. // Synopsis: Take a string, and expand any macros in it. (e.g.
  439. // "$(BASEDIR)\foobar\myfile.lib" is expanded to
  440. // "f:\nt\private\foobar\myfile.lib" if $(BASEDIR) has a value of
  441. // "f:\nt\private".
  442. //
  443. // Arguments: [pp] -- Output string
  444. // [psrc] -- Input string
  445. //
  446. // Returns:
  447. //
  448. // Notes: Any previous string value in [pp] is freed before updating it.
  449. //
  450. //----------------------------------------------------------------------------
  451. char MMSBuffer[64*1024];
  452. BOOL
  453. MakeMacroString(LPSTR *pp, LPSTR psrc)
  454. {
  455. LPSTR pname, p2, pdst, p3;
  456. int cb;
  457. char chTerminator;
  458. int cNameChars;
  459. int cChars;
  460. pdst = MMSBuffer;
  461. cb = strlen(psrc);
  462. if (cb > sizeof(MMSBuffer) - 1) {
  463. BuildError(
  464. "(Fatal Error) Buffer overflow: MakeMacroString(%s)\r\n",
  465. psrc);
  466. exit(16);
  467. }
  468. while ((pname = strchr(psrc, '$')) != NULL &&
  469. ((pname[1] == LPAREN &&
  470. (p2 = strchr(pname, RPAREN)) != NULL) ||
  471. (MACRO_CHAR(pname[1]) &&
  472. !MACRO_CHAR(pname[2])))) {
  473. LPSTR pszvalue;
  474. // Handle one-character non-paren macro usage.
  475. if (pname[1] == LPAREN) {
  476. // Initialize cNameChars with the number of chars to
  477. // skip to get to the first name character.
  478. cNameChars = 2;
  479. } else {
  480. p2 = pname + 2;
  481. cNameChars = 1;
  482. }
  483. chTerminator = *p2;
  484. *pname = *p2 = '\0';
  485. // copy up to macro name
  486. cChars = strlen(psrc);
  487. memcpy(pdst, psrc, cChars + 1);
  488. psrc += cChars;
  489. pdst += cChars;
  490. *pname = '$';
  491. pname += cNameChars;
  492. cNameChars += strlen(pname) + (chTerminator == RPAREN ? 1 : 0);
  493. p3 = NULL;
  494. if (chTerminator == RPAREN &&
  495. (p3 = strchr(pname, ':')) != NULL) {
  496. // macro substitution exists. ie: $(foo:old=new)
  497. *p3 = '\0';
  498. }
  499. if ((pszvalue = FindMacro(pname)) == NULL &&
  500. (pszvalue = getenv(pname)) == NULL &&
  501. (pszvalue = GetBaseDir(pname)) == NULL) {
  502. pszvalue = ""; // can't find macro name -- ignore it
  503. }
  504. if (p3) {
  505. char *pNew = malloc(10);
  506. char *pResult = pNew;
  507. char *pEnd = pNew+10;
  508. unsigned Len = 10;
  509. if (!pNew) {
  510. BuildError("(Fatal Error) Internal buffer overflow: MakeMacroString(%s[%s = %s]%s)\r\n",
  511. MMSBuffer,
  512. pname,
  513. pszvalue,
  514. p2 + 1);
  515. exit(16);
  516. }
  517. *p3 = ':';
  518. *p2=RPAREN;
  519. SubstituteString(&pResult, &p3, &pNew, &pEnd, pszvalue, &Len);
  520. *pNew = '\0';
  521. *p2='\0';
  522. pszvalue = pResult;
  523. }
  524. cb += strlen(pszvalue) - cNameChars;
  525. assert(cb >= 0);
  526. if (cb > sizeof(MMSBuffer) - 1) {
  527. BuildError(
  528. "(Fatal Error) Internal buffer overflow: MakeMacroString(%s[%s = %s]%s)\r\n",
  529. MMSBuffer,
  530. pname,
  531. pszvalue,
  532. p2 + 1);
  533. exit(16);
  534. }
  535. strcpy(pdst, pszvalue); // copy expanded value
  536. if (p3) {
  537. free(pszvalue);
  538. }
  539. pdst += strlen(pdst);
  540. *p2 = chTerminator;
  541. psrc += cNameChars;
  542. }
  543. strcpy(pdst, psrc); // copy rest of string
  544. if (pdst != MMSBuffer) {
  545. CompressBlanks(MMSBuffer);
  546. }
  547. p2 = *pp;
  548. *pp = NULL;
  549. if (MMSBuffer[0] != '\0') {
  550. MakeString(pp, MMSBuffer, TRUE, MT_DIRSTRING);
  551. }
  552. if (p2 != NULL) {
  553. FreeMem(&p2, MT_DIRSTRING);
  554. }
  555. return (MMSBuffer[0] != '\0');
  556. }
  557. //+---------------------------------------------------------------------------
  558. //
  559. // Function: SetMacroString
  560. //
  561. // Synopsis: If the two macro names are the same, store the value in that
  562. // macro
  563. //
  564. // Arguments: [pMacro1] -- Name of first macro
  565. // [pMacro2] -- Name of second macro
  566. // [pValue] -- Unexpanded value to store.
  567. // [ppValue] -- Expanded value of macro.
  568. //
  569. // Returns: BOOL
  570. //
  571. //----------------------------------------------------------------------------
  572. BOOL
  573. SetMacroString(LPSTR pMacro1, LPSTR pMacro2, LPSTR pValue, LPSTR *ppValue)
  574. {
  575. if (_stricmp(pMacro1, pMacro2) == 0) {
  576. MakeMacroString(ppValue, pValue);
  577. return (TRUE); // return TRUE even if MakeMacroString stored a NULL
  578. }
  579. return (FALSE);
  580. }
  581. //+---------------------------------------------------------------------------
  582. //
  583. // Function: SplitToken
  584. //
  585. // Synopsis: Split the string at the given separator character or space.
  586. //
  587. // Arguments: [pbuf] -- First part of split string returned here.
  588. // [chsep] -- Separator character.
  589. // [ppstr] -- Source string to split. Becomes the second half.
  590. //
  591. // Returns: TRUE if the split was successful. FALSE if it wasn't split.
  592. //
  593. // Notes: If *ppstr = "path\filename" and chsep = '\' on input, then
  594. // pbuf = "path" and *ppstr = "\filename" on output.
  595. //
  596. //----------------------------------------------------------------------------
  597. BOOL
  598. SplitToken(LPSTR pbuf, char chsep, LPSTR *ppstr)
  599. {
  600. LPSTR psrc, pdst;
  601. psrc = *ppstr;
  602. pdst = pbuf;
  603. //BuildError("SplitToken('%c', '%s') ==> ", chsep, psrc);
  604. while (*psrc == chsep || *psrc == ' ') {
  605. psrc++;
  606. }
  607. while (*psrc != '\0' && *psrc != chsep && *psrc != ' ') {
  608. *pdst = *psrc++;
  609. if (*pdst == '/') {
  610. *pdst = '\\';
  611. }
  612. pdst++;
  613. }
  614. *pdst = '\0';
  615. *ppstr = psrc;
  616. //BuildErrorRaw("('%s', '%s')\r\n", psrc, pbuf);
  617. return (pdst != pbuf);
  618. }
  619. //+---------------------------------------------------------------------------
  620. //
  621. // Function: CrackSources
  622. //
  623. // Synopsis: Parse the SOURCES= line in a sources file and adds those source
  624. // files to the list of sources in the DIRREC struct.
  625. //
  626. // Arguments: [pdr] -- Directory record
  627. // [pds] -- Supplemental directory information
  628. // [i] -- Which platform we're parsing
  629. //
  630. //----------------------------------------------------------------------------
  631. VOID
  632. CrackSources(
  633. DIRREC *pdr,
  634. DIRSUP *pds,
  635. int i)
  636. {
  637. LPSTR pszsubdir, plist;
  638. LPSTR pszfile, pszpath;
  639. FILEREC *pfr;
  640. DIRREC *pdrAssociate;
  641. DIRREC *pdrParent;
  642. DIRREC *pdrMachine;
  643. DIRREC *pdrParentMachine;
  644. DIRREC *pdrTarget;
  645. DIRREC **ppdr;
  646. LPSTR pszSources;
  647. char path[DB_MAX_PATH_LENGTH];
  648. TARGET_MACHINE_INFO *pMachine;
  649. switch (i) {
  650. case 0:
  651. pMachine = TargetMachines[0];
  652. pszSources = "SOURCES";
  653. break;
  654. case 1:
  655. pMachine = TargetMachines[0];
  656. pszSources = "OBJLIBFILES";
  657. break;
  658. default:
  659. pMachine = PossibleTargetMachines[i - 2];
  660. pszSources = pMachine->SourceVariable;
  661. break;
  662. }
  663. pdrAssociate = pdrParent = pdrMachine = pdrParentMachine = pdrTarget = NULL;
  664. plist = pds->SourcesVariables[i];
  665. while (SplitToken(path, ' ', &plist)) {
  666. UCHAR SubDirMask, SrcFlags;
  667. SubDirMask = 0;
  668. ppdr = &pdr; // assume current directory
  669. pszsubdir = path;
  670. if (pszsubdir[0] == '.' && pszsubdir[1] == '\\') {
  671. BuildError(
  672. "%s: Ignoring current directory prefix in %s= entry: %s\r\n",
  673. pdr->Name,
  674. pszSources,
  675. path);
  676. pszsubdir += 2;
  677. }
  678. if (pszsubdir[0] == '.' &&
  679. pszsubdir[1] == '.' &&
  680. pszsubdir[2] == '\\') {
  681. SubDirMask = TMIDIR_PARENT;
  682. ppdr = &pdrParent; // assume parent directory
  683. pszsubdir += 3;
  684. }
  685. pszpath = path;
  686. pszfile = strchr(pszsubdir, '\\');
  687. if (pszfile == NULL) {
  688. pszfile = pszsubdir;
  689. } else {
  690. LPSTR pszSecondSlash;
  691. LPSTR pszAssociateDir;
  692. LPSTR pszMachineDir;
  693. // Check for second slash and handle $O\. If there is
  694. // no second slash, check for a machine specific directory name.
  695. // Second slashes are not legal if there's already been
  696. // a '..'.
  697. if ((SubDirMask & TMIDIR_PARENT) == 0) {
  698. pszSecondSlash = strchr(pszfile + 1, '\\');
  699. if (pszSecondSlash != NULL) {
  700. pszfile = pszSecondSlash;
  701. }
  702. } else {
  703. pszSecondSlash = NULL;
  704. }
  705. *pszfile = '\0';
  706. if (pszSecondSlash != NULL) {
  707. pszMachineDir = pMachine->ObjectDirectory[iObjectDir];
  708. pszAssociateDir = pszMachineDir;
  709. } else {
  710. pszMachineDir = pMachine->SourceDirectory;
  711. pszAssociateDir = pMachine->AssociateDirectory;
  712. }
  713. if (((_stricmp(pszsubdir, pszAssociateDir) != 0) &&
  714. (_stricmp(pszsubdir, pszMachineDir) != 0)) ||
  715. strchr(pszfile + 1, '\\') != NULL) {
  716. *pszfile = '\\';
  717. /*
  718. * Managed code such as C# and VB.NET builds fine with a
  719. * "prefix" directory, so don't complain in that case.
  720. */
  721. if (!(pdr->DirFlags & DIRDB_MANAGED_CODE) && strcmp(pszSources, "OBJLIBFILES")) {
  722. BuildError(
  723. "%s: Ignoring invalid directory prefix in %s= entry: %s\r\n",
  724. pdr->Name,
  725. pszSources,
  726. path);
  727. }
  728. pszpath = strrchr(path, '\\');
  729. assert(pszpath != NULL);
  730. pszpath++;
  731. SubDirMask = 0;
  732. ppdr = &pdr; // default to current direcory
  733. } else {
  734. SubDirMask |= pMachine->SourceSubDirMask;
  735. *pszfile++ = '\\';
  736. if (SubDirMask & TMIDIR_PARENT) {
  737. ppdr = &pdrParentMachine;
  738. } else if (pszSecondSlash != NULL) {
  739. // Must have matched $O.
  740. ppdr = &pdrTarget;
  741. } else {
  742. if (_stricmp(pszsubdir, pszMachineDir) != 0) {
  743. ppdr = &pdrMachine;
  744. } else {
  745. ppdr = &pdrAssociate;
  746. }
  747. }
  748. }
  749. }
  750. NewDirectory:
  751. if (*ppdr == NULL) {
  752. pfr = FindSourceFileDB(pdr, pszpath, ppdr);
  753. } else {
  754. pfr = LookupFileDB(*ppdr, pszfile);
  755. }
  756. SrcFlags = SOURCEDB_SOURCES_LIST;
  757. if ((pfr == NULL) && !fPassZero) {
  758. if (fDebug) {
  759. BuildError("%s: Missing source file: %s\r\n", pdr->Name, path);
  760. }
  761. if (*ppdr == NULL) {
  762. if (fDebug || pszpath == path) {
  763. BuildError(
  764. "%s: Directory does not exist: %s\r\n",
  765. pdr->Name,
  766. path);
  767. }
  768. // Probably an error in the subordinate sources file.
  769. // since old versions of build managed to get these entries
  770. // into the objects lists, we have to do the same...
  771. //
  772. // If ..\ prefix exists, strip it off and try again.
  773. // Else try again with the current directory.
  774. if (SubDirMask & TMIDIR_PARENT) {
  775. SubDirMask &= ~TMIDIR_PARENT; // strip off "..\\"
  776. } else {
  777. SubDirMask = 0; // use current direcory
  778. }
  779. if (SubDirMask == 0) {
  780. ppdr = &pdr; // current direcory
  781. pszpath = pszfile;
  782. } else {
  783. ppdr = &pdrMachine; // machine sub dir
  784. pszpath = pszsubdir;
  785. }
  786. goto NewDirectory;
  787. }
  788. pfr = InsertFileDB(*ppdr, pszfile, 0, 0, FILEDB_FILE_MISSING);
  789. if (pfr == NULL && strcmp(pszSources, "OBJLIBFILES")) {
  790. BuildError(
  791. "%s: Ignoring invalid %s= entry: %s\r\n",
  792. pdr->Name,
  793. pszSources,
  794. path);
  795. }
  796. }
  797. if (pfr != NULL) {
  798. AssertFile(pfr);
  799. if (SubDirMask == 0) {
  800. pfr->FileFlags |= FILEDB_OBJECTS_LIST;
  801. }
  802. if (pfr->FileFlags & FILEDB_FILE_MISSING) {
  803. SrcFlags |= SOURCEDB_FILE_MISSING;
  804. }
  805. InsertSourceDB(&pds->psrSourcesList[i], pfr, SubDirMask, SrcFlags);
  806. }
  807. }
  808. }
  809. //+---------------------------------------------------------------------------
  810. //
  811. // Function: SaveUserTests
  812. //
  813. // Synopsis: Save the value of the UMTEST macro into the DIRREC struct.
  814. //
  815. // Arguments: [DirDB] -- Dir struct to save into
  816. // [TextLine] -- String from UMTEST= line in sources file
  817. //
  818. //----------------------------------------------------------------------------
  819. VOID
  820. SaveUserTests(
  821. PDIRREC DirDB,
  822. LPSTR TextLine)
  823. {
  824. UINT i;
  825. BOOL fSave = FALSE;
  826. char name[DB_MAX_PATH_LENGTH];
  827. char buf[512];
  828. buf[0] = '\0';
  829. if (DirDB->UserTests != NULL) {
  830. strcpy(buf, DirDB->UserTests);
  831. }
  832. CopyString(TextLine, TextLine, TRUE);
  833. while (SplitToken(name, '*', &TextLine)) {
  834. for (i = 0; i < CountOptionalDirs; i++) {
  835. if (!strcmp(name, OptionalDirs[i])) {
  836. if (buf[0] != '\0') {
  837. strcat(buf, "*");
  838. DirDB->DirFlags |= DIRDB_FORCELINK; // multiple targets
  839. }
  840. strcat(buf, name);
  841. fSave = TRUE;
  842. break;
  843. }
  844. }
  845. }
  846. if (fSave) {
  847. MakeMacroString(&DirDB->UserTests, buf);
  848. DirDB->DirFlags |= DIRDB_LINKNEEDED;
  849. }
  850. }
  851. void
  852. AddProduceDependency(
  853. DIRREC *DirDB,
  854. LPSTR Value
  855. )
  856. {
  857. char produces[DB_MAX_PATH_LENGTH];
  858. PDEPENDENCY Dependency;
  859. while (SplitToken(produces, ' ',&Value)) {
  860. AllocMem(sizeof(DEPENDENCY)+strlen(produces), &Dependency, MT_DEPENDENCY);
  861. InitializeListHead(&Dependency->WaitList);
  862. InsertTailList(&DirDB->Produces, &Dependency->DependencyList);
  863. Dependency->Producer = DirDB;
  864. strcpy(Dependency->Name, produces);
  865. Dependency->CheckSum = CheckSum(Dependency->Name);
  866. Dependency->Next = AllDependencies;
  867. Dependency->Done = FALSE;
  868. Dependency->hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  869. if (Dependency->hEvent == NULL) {
  870. BuildMsg("Failed to create dependency hEvent for dependency %s in directory %s\n",
  871. Dependency, DirDB->Name);
  872. }
  873. AllDependencies = Dependency;
  874. }
  875. }
  876. void
  877. AddConsumeDependency(
  878. DIRREC *DirDB,
  879. LPSTR Value
  880. )
  881. {
  882. char consumes[DB_MAX_PATH_LENGTH];
  883. PDEPENDENCY Dependency;
  884. PDEPENDENCY_WAIT Wait;
  885. USHORT sum;
  886. while (SplitToken(consumes, ' ',&Value)) {
  887. //
  888. // Find the dependency, which must have already been created by the
  889. // producer.
  890. //
  891. sum = CheckSum(consumes);
  892. Dependency = AllDependencies;
  893. while (Dependency) {
  894. if ((Dependency->CheckSum == sum) &&
  895. (strcmp(Dependency->Name, consumes)==0)) {
  896. break;
  897. }
  898. Dependency = Dependency->Next;
  899. }
  900. if (Dependency != NULL) {
  901. AllocMem(sizeof(DEPENDENCY_WAIT), &Wait, MT_DEPENDENCY_WAIT);
  902. InsertTailList(&DirDB->Consumes, &Wait->ListEntry);
  903. Wait->Consumer = DirDB;
  904. Wait->Dependency = Dependency;
  905. }
  906. }
  907. }
  908. //+---------------------------------------------------------------------------
  909. //
  910. // Function: ProcessSourcesFileLine
  911. //
  912. // Synopsis: Given a line from a sources file, do the right thing.
  913. //
  914. // Arguments: [DirDB] -- Directory containing sources file
  915. // [pds] -- Supplementary info on directory
  916. // [TextLine] -- Line to process
  917. //
  918. // Returns: void
  919. //
  920. //----------------------------------------------------------------------------
  921. void
  922. ProcessSourcesFileLine(
  923. DIRREC *DirDB, // Current Directory record
  924. DIRSUP *pds, // Supplemental Directory record
  925. LPSTR TextLine, // Line to process
  926. int iTarget // Index into target machine array.
  927. )
  928. {
  929. LPSTR MacroName, p1;
  930. UINT i, iMacro;
  931. char path[DB_MAX_PATH_LENGTH];
  932. BOOL fCleanNTTargetFile0 = FALSE;
  933. LPSTR pValue; // right side of equal sign
  934. LPSTR pszTemp=NULL;
  935. pValue = SplitMacro(&TextLine);
  936. if (pValue == NULL) {
  937. return;
  938. }
  939. // Note: TextLine is now the left side of the equal sign. See if it's interesting.
  940. //
  941. // This sets pds->SourcesVariables[0] to the value of SOURCES= if
  942. // the current line is SOURCES=...
  943. //
  944. if (SetMacroString(
  945. "SOURCES",
  946. TextLine,
  947. pValue,
  948. &pds->SourcesVariables[0])) {
  949. DirDB->DirFlags |= DIRDB_SOURCES_SET;
  950. goto SaveAndFreeMacro;
  951. } else if (SetMacroString(
  952. "OBJLIBFILES",
  953. TextLine,
  954. pValue,
  955. &pds->SourcesVariables[1])) {
  956. DirDB->DirFlags |= DIRDB_SOURCES_SET;
  957. goto SaveAndFreeMacro;
  958. } else {
  959. for (i = 0; i < MAX_TARGET_MACHINES; i++) {
  960. //
  961. // This sets pds->SourcesVariables[0] to the value of
  962. // PLAT_SOURCES= if the current line is PLAT_SOURCES=...
  963. //
  964. if (SetMacroString(
  965. PossibleTargetMachines[i]->SourceVariable,
  966. TextLine,
  967. pValue,
  968. &pds->SourcesVariables[i + 2])) {
  969. DirDB->DirFlags |= DIRDB_SOURCES_SET;
  970. goto SaveAndFreeMacro;
  971. }
  972. }
  973. }
  974. // Not a SOURCES or xxx_SOURCES macro, check against all the other interesting
  975. // macro names.
  976. iMacro = 0;
  977. while ((MacroName = RelevantSourcesMacros[iMacro]) != NULL) {
  978. if (_stricmp(TextLine, MacroName) == 0) {
  979. break;
  980. }
  981. iMacro++;
  982. }
  983. if (MacroName != NULL) { // if macro name found in list
  984. switch (iMacro) {
  985. case SOURCES_TARGETNAME:
  986. MakeMacroString(&DirDB->TargetName, pValue);
  987. break;
  988. case SOURCES_TARGETPATH:
  989. if (strcmp(pValue, "obj") == 0) {
  990. pValue = pszObjDir;
  991. }
  992. MakeMacroString(&DirDB->TargetPath, pValue);
  993. if (DirDB->TargetPath != NULL) {
  994. CreateBuildDirectory(DirDB->TargetPath);
  995. for (i = 0; i < CountTargetMachines; i++) {
  996. p1 = TargetMachines[i]->ObjectDirectory[iObjectDir];
  997. assert(strncmp(pszObjDirSlash, p1, strlen(pszObjDirSlash)) == 0);
  998. p1 += strlen(pszObjDirSlash);
  999. sprintf(path, "%s\\%s", DirDB->TargetPath, p1);
  1000. CreateBuildDirectory(path);
  1001. }
  1002. }
  1003. break;
  1004. case SOURCES_TARGETPATHLIB:
  1005. if (strcmp(pValue, "obj") == 0) {
  1006. pValue = pszObjDir;
  1007. }
  1008. MakeMacroString(&DirDB->TargetPathLib, pValue);
  1009. if (DirDB->TargetPathLib != NULL) {
  1010. CreateBuildDirectory(DirDB->TargetPathLib);
  1011. for (i = 0; i < CountTargetMachines; i++) {
  1012. p1 = TargetMachines[i]->ObjectDirectory[iObjectDir];
  1013. assert(strncmp(pszObjDirSlash, p1, strlen(pszObjDirSlash)) == 0);
  1014. p1 += strlen(pszObjDirSlash);
  1015. sprintf(path, "%s\\%s", DirDB->TargetPathLib, p1);
  1016. CreateBuildDirectory(path);
  1017. }
  1018. }
  1019. break;
  1020. case SOURCES_TARGETTYPE:
  1021. if (!_stricmp(pValue, "PROGRAM") || !_stricmp(pValue, "PROGLIB")) {
  1022. MakeMacroString(&DirDB->TargetExt, ".exe");
  1023. DirDB->DirFlags |= DIRDB_LINKNEEDED;
  1024. } else if (!_stricmp(pValue, "OBJLIB")) {
  1025. MakeMacroString(&DirDB->TargetExt, ".olb");
  1026. DirDB->DirFlags |= DIRDB_LINKNEEDED;
  1027. } else if (!_stricmp(pValue, "DRIVER") || !_stricmp(pValue, "MINIPORT")) {
  1028. MakeMacroString(&DirDB->TargetExt, ".sys");
  1029. DirDB->DirFlags |= DIRDB_LINKNEEDED;
  1030. } else if (!_stricmp(pValue, "GDI_DRIVER")) {
  1031. MakeMacroString(&DirDB->TargetExt, ".dll");
  1032. DirDB->DirFlags |= DIRDB_LINKNEEDED;
  1033. } else if (!_stricmp(pValue, "EXPORT_DRIVER")) {
  1034. MakeMacroString(&DirDB->TargetExt, ".sys");
  1035. DirDB->DirFlags |= DIRDB_LINKNEEDED;
  1036. DirDB->DirFlags |= DIRDB_DLLTARGET;
  1037. } else if (!_stricmp(pValue, "DYNLINK") || !_stricmp(pValue, "HAL")) {
  1038. MakeMacroString(&DirDB->TargetExt, ".dll");
  1039. DirDB->DirFlags |= DIRDB_LINKNEEDED;
  1040. DirDB->DirFlags |= DIRDB_DLLTARGET;
  1041. } else if ((!_stricmp(pValue, "LIBRARY")) || (!_stricmp(pValue, "DRIVER_LIBRARY"))) {
  1042. MakeMacroString(&DirDB->TargetExt, ".lib");
  1043. DirDB->DirFlags &= ~DIRDB_LINKNEEDED;
  1044. } else if (!_stricmp(pValue, "UMAPPL_NOLIB")) {
  1045. DirDB->DirFlags &= ~DIRDB_LINKNEEDED;
  1046. } else if (!_stricmp(pValue, "NOTARGET")) {
  1047. //
  1048. // Used to indicate no target for a directory,
  1049. // e.g. if only pass0 files are generated
  1050. pds->fNoTarget = TRUE;
  1051. if (!fQuicky || (fQuickZero && fFirstScan)) {
  1052. DirDB->DirFlags |= DIRDB_PASS0NEEDED;
  1053. }
  1054. } else {
  1055. BuildError( "Unsupported TARGETTYPE value - %s\r\n", pValue);
  1056. }
  1057. break;
  1058. case SOURCES_TARGETEXT:
  1059. {
  1060. char TargetExt[_MAX_EXT] = ".";
  1061. strcat(TargetExt, pValue);
  1062. MakeMacroString(&DirDB->TargetExt, TargetExt);
  1063. }
  1064. break;
  1065. case SOURCES_INCLUDES:
  1066. MakeMacroString(&pds->LocalIncludePath, pValue);
  1067. if (DEBUG_1) {
  1068. BuildMsg(
  1069. " Found local INCLUDES=%s\r\n",
  1070. pds->LocalIncludePath);
  1071. }
  1072. break;
  1073. case SOURCES_USER_INCLUDES:
  1074. MakeMacroString(&pds->UserIncludePath, pValue);
  1075. if (DEBUG_1) {
  1076. BuildMsg(
  1077. " Found local USER_INCLUDES=%s\r\n",
  1078. pds->UserIncludePath);
  1079. }
  1080. break;
  1081. case SOURCES_LAST_INCLUDES:
  1082. MakeMacroString(&pds->LastIncludePath, pValue);
  1083. if (DEBUG_1) {
  1084. BuildMsg(
  1085. " Found local LAST_INCLUDES=%s\r\n",
  1086. pds->LastIncludePath);
  1087. }
  1088. break;
  1089. case SOURCES_MFC_INCLUDES:
  1090. // MFC_INCLUDES/SDK_INC/CRT_INC/OAK_INC really can't be changed
  1091. // in the sources file (yet) since we've already processed the
  1092. // system includes. Lay the groundwork for now.
  1093. MakeMacroString((char **)&pszIncMfc, pValue);
  1094. break;
  1095. case SOURCES_SDK_LIB_DEST:
  1096. MakeMacroString((char **)&pszSdkLibDest, pValue);
  1097. break;
  1098. case SOURCES_DDK_LIB_DEST:
  1099. MakeMacroString((char **)&pszDdkLibDest, pValue);
  1100. break;
  1101. case SOURCES_SDK_INC_PATH:
  1102. MakeMacroString((char **)&pszIncSdk, pValue);
  1103. break;
  1104. case SOURCES_CRT_INC_PATH:
  1105. MakeMacroString((char **)&pszIncCrt, pValue);
  1106. break;
  1107. case SOURCES_OAK_INC_PATH:
  1108. MakeMacroString((char **)&pszIncOak, pValue);
  1109. break;
  1110. case SOURCES_DDK_INC_PATH:
  1111. MakeMacroString((char **)&pszIncDdk, pValue);
  1112. break;
  1113. case SOURCES_WDM_INC_PATH:
  1114. MakeMacroString((char **)&pszIncWdm, pValue);
  1115. break;
  1116. case SOURCES_PRIVATE_INC_PATH:
  1117. MakeMacroString((char **)&pszIncPri, pValue);
  1118. break;
  1119. case SOURCES_PRECOMPILED_PCH:
  1120. MakeMacroString(&DirDB->Pch, pValue);
  1121. break;
  1122. case SOURCES_PRECOMPILED_OBJ:
  1123. MakeMacroString(&DirDB->PchObj, pValue);
  1124. break;
  1125. case SOURCES_PRECOMPILED_INCLUDE:
  1126. case SOURCES_PRECOMPILED_TARGET:
  1127. {
  1128. LPSTR *ppszPath, *ppszFile, p;
  1129. if (iMacro == SOURCES_PRECOMPILED_INCLUDE) {
  1130. ppszPath = &pds->PchIncludeDir;
  1131. ppszFile = &pds->PchInclude;
  1132. } else {
  1133. ppszPath = &pds->PchTargetDir;
  1134. ppszFile = &pds->PchTarget;
  1135. }
  1136. MakeMacroString(ppszPath, ""); // free old string
  1137. if (!MakeMacroString(ppszFile, pValue)) {
  1138. break;
  1139. }
  1140. p = *ppszFile + strlen(*ppszFile);
  1141. while (p > *ppszFile && *--p != '\\')
  1142. ;
  1143. if (p > *ppszFile) {
  1144. *p = '\0';
  1145. MakeMacroString(ppszPath, *ppszFile);
  1146. MakeMacroString(ppszFile, p + 1);
  1147. }
  1148. if (DEBUG_1) {
  1149. BuildMsg(
  1150. "Precompiled header%s is %s in directory %s\r\n",
  1151. iMacro == SOURCES_PRECOMPILED_INCLUDE?
  1152. "" : " target",
  1153. *ppszFile,
  1154. *ppszPath != NULL?
  1155. *ppszPath : "'.'");
  1156. }
  1157. }
  1158. if (iMacro == SOURCES_PRECOMPILED_INCLUDE ||
  1159. pds->PchTargetDir == NULL) {
  1160. break;
  1161. }
  1162. EnsureDirectoriesExist(pds->PchTargetDir);
  1163. break;
  1164. case SOURCES_PASS0_HEADERDIR:
  1165. MakeMacroString(&pds->PassZeroHdrDir, pValue);
  1166. EnsureDirectoriesExist(pds->PassZeroHdrDir);
  1167. if (DEBUG_1) {
  1168. BuildMsg("Pass Zero Header Directory is '%s'\r\n",
  1169. pds->PassZeroHdrDir);
  1170. }
  1171. break;
  1172. case SOURCES_PASS0_SOURCEDIR:
  1173. // SOURCES_PASS0_SOURCEDIR and SOURCES_PASS0_CLIENTDIR
  1174. // are mutually exclusive - enforced by makefile.def
  1175. DirDB->DirFlags &= ~DIRDB_IDLTYPERPC;
  1176. MakeMacroString(&pds->PassZeroSrcDir1, pValue);
  1177. EnsureDirectoriesExist(pds->PassZeroSrcDir1);
  1178. if (DEBUG_1) {
  1179. BuildMsg("Pass Zero Source Directory is '%s'\r\n",
  1180. pds->PassZeroSrcDir1);
  1181. }
  1182. break;
  1183. case SOURCES_PASS0_CLIENTDIR:
  1184. // SOURCES_PASS0_SOURCEDIR and SOURCES_PASS0_CLIENTDIR
  1185. // are mutually exclusive - enforced by makefile.def
  1186. DirDB->DirFlags |= DIRDB_IDLTYPERPC;
  1187. MakeMacroString(&pds->PassZeroSrcDir1, pValue);
  1188. EnsureDirectoriesExist(pds->PassZeroSrcDir1);
  1189. if (DEBUG_1) {
  1190. BuildMsg("Pass Zero Client Directory is '%s'\r\n",
  1191. pds->PassZeroSrcDir1);
  1192. }
  1193. break;
  1194. case SOURCES_MIDL_UUIDDIR:
  1195. case SOURCES_PASS0_UUIDDIR:
  1196. // SOURCES_PASS0_UUIDDIR and SOURCES_PASS0_SERVERDIR
  1197. // are mutually exclusive - enforced by makefile.def
  1198. DirDB->DirFlags &= ~DIRDB_IDLTYPERPC;
  1199. MakeMacroString(&pds->PassZeroSrcDir2, pValue);
  1200. EnsureDirectoriesExist(pds->PassZeroSrcDir2);
  1201. if (DEBUG_1) {
  1202. BuildMsg("Pass Zero UUID Source Directory is '%s'\r\n",
  1203. pds->PassZeroSrcDir2);
  1204. }
  1205. break;
  1206. case SOURCES_PASS0_SERVERDIR:
  1207. // SOURCES_PASS0_UUIDDIR and SOURCES_PASS0_SERVERDIR
  1208. // are mutually exclusive - enforced by makefile.def
  1209. DirDB->DirFlags |= DIRDB_IDLTYPERPC;
  1210. MakeMacroString(&pds->PassZeroSrcDir2, pValue);
  1211. EnsureDirectoriesExist(pds->PassZeroSrcDir2);
  1212. if (DEBUG_1) {
  1213. BuildMsg("Pass Zero Server Directory is '%s'\r\n",
  1214. pds->PassZeroSrcDir2);
  1215. }
  1216. break;
  1217. case SOURCES_NTTEST:
  1218. if (MakeMacroString(&DirDB->KernelTest, pValue)) {
  1219. DirDB->DirFlags |= DIRDB_LINKNEEDED;
  1220. }
  1221. break;
  1222. case SOURCES_UMTYPE:
  1223. MakeMacroString(&pds->TestType, pValue);
  1224. if (DEBUG_1) {
  1225. BuildMsg(
  1226. " Found UMTYPE=%s\r\n",
  1227. pds->TestType);
  1228. }
  1229. break;
  1230. case SOURCES_UMTEST:
  1231. case SOURCES_OPTIONAL_UMTEST:
  1232. SaveUserTests(DirDB, pValue);
  1233. break;
  1234. case SOURCES_UMAPPL:
  1235. if (MakeMacroString(&DirDB->UserAppls, pValue)) {
  1236. DirDB->DirFlags |= DIRDB_LINKNEEDED;
  1237. }
  1238. break;
  1239. case SOURCES_UMAPPLEXT:
  1240. if (!_stricmp(pValue, ".exe")) {
  1241. MakeMacroString(&DirDB->TargetExt, ".exe");
  1242. } else
  1243. if (!_stricmp(pValue, ".com")) {
  1244. MakeMacroString(&DirDB->TargetExt, ".com");
  1245. } else
  1246. if (!_stricmp(pValue, ".scr")) {
  1247. MakeMacroString(&DirDB->TargetExt, ".scr");
  1248. } else {
  1249. BuildError(
  1250. "Unsupported UMAPPLEXT value - %s\r\n",
  1251. pValue);
  1252. }
  1253. break;
  1254. case SOURCES_IDLTYPE:
  1255. if (!_stricmp(pValue, "ole")) {
  1256. pds->IdlType = 0;
  1257. } else
  1258. if (!_stricmp(pValue, "rpc")) {
  1259. pds->IdlType = 1;
  1260. } else {
  1261. BuildError(
  1262. "Unsupported IDL_TYPE value - %s\r\n",
  1263. pValue);
  1264. }
  1265. break;
  1266. case SOURCES_SOURCES_OPTIONS:
  1267. fCleanNTTargetFile0 = fClean && strstr(pValue, "-c0");
  1268. break;
  1269. case SOURCES_NTTARGETFILE0:
  1270. DirDB->DirFlags |= DIRDB_TARGETFILE0;
  1271. if (fCleanNTTargetFile0) {
  1272. MakeMacroString(&DirDB->NTTargetFile0, pValue);
  1273. }
  1274. break;
  1275. case SOURCES_NTTARGETFILES:
  1276. DirDB->DirFlags |= DIRDB_TARGETFILES;
  1277. break;
  1278. case SOURCES_CHICAGO_PRODUCT:
  1279. DirDB->DirFlags |= DIRDB_CHICAGO_INCLUDES;
  1280. break;
  1281. case SOURCES_CONDITIONAL_INCLUDES:
  1282. MakeMacroString(&pds->ConditionalIncludes, pValue);
  1283. break;
  1284. case SOURCES_SYNCHRONIZE_BLOCK:
  1285. //if ((!fIgnoreSync) && !(DirDB->DirFlags & (DIRDB_SYNC_PRODUCES | DIRDB_SYNC_CONSUMES))) {
  1286. if (!fIgnoreSync) {
  1287. DirDB->DirFlags |= DIRDB_SYNCHRONIZE_BLOCK;
  1288. }
  1289. break;
  1290. case SOURCES_SYNCHRONIZE_PASS2_BLOCK:
  1291. DirDB->DirFlags |= DIRDB_SYNCHRONIZE_PASS2_BLOCK;
  1292. break;
  1293. case SOURCES_SYNCHRONIZE_DRAIN:
  1294. // if ((!fIgnoreSync) && !(DirDB->DirFlags & (DIRDB_SYNC_PRODUCES | DIRDB_SYNC_CONSUMES))) {
  1295. if ((!fIgnoreSync) && !(DirDB->DirFlags & DIRDB_SYNC_CONSUMES)) {
  1296. DirDB->DirFlags |= DIRDB_SYNCHRONIZE_DRAIN;
  1297. }
  1298. break;
  1299. case SOURCES_SYNCHRONIZE_PASS2_DRAIN:
  1300. DirDB->DirFlags |= DIRDB_SYNCHRONIZE_PASS2_DRAIN;
  1301. break;
  1302. case SOURCES_CHECKED_ALT_DIR:
  1303. if (!fBuildAltDirSet) {
  1304. DirDB->DirFlags |= DIRDB_CHECKED_ALT_DIR;
  1305. if (DEBUG_1) {
  1306. BuildMsg("Found CHECKED_ALT_DIR\r\n");
  1307. }
  1308. SetObjDir(TRUE);
  1309. if (fCheckedBuild) {
  1310. SaveMacro("_OBJ_DIR", pszObjDir);
  1311. if (iTarget < 0) {
  1312. SaveMacro("O", TargetMachines[0]->
  1313. ObjectDirectory[iObjectDir]);
  1314. } else {
  1315. SaveMacro("O",
  1316. PossibleTargetMachines[iTarget/2]->
  1317. ObjectDirectory[iObjectDir]);
  1318. }
  1319. }
  1320. }
  1321. break;
  1322. case SOURCES_PROJECT_NAME:
  1323. sprintf(path, "%s\\%s", NtRoot, pValue);
  1324. SaveMacro("PROJECT_ROOT", path);
  1325. break;
  1326. case SOURCES_PASS0_PUBLISH:
  1327. DirDB->DirFlags |= DIRDB_PASS0NEEDED;
  1328. break;
  1329. case SOURCES_MANAGED_CODE:
  1330. case SOURCES_MANAGED_VB:
  1331. DirDB->DirFlags |= DIRDB_MANAGED_CODE;
  1332. break;
  1333. case SOURCES_SYNC_PRODUCES:
  1334. DirDB->DirFlags |= DIRDB_SYNC_PRODUCES;
  1335. //A producer directory can be a BLOCK or a DRAIN.
  1336. //DirDB->DirFlags &= ~(DIRDB_SYNCHRONIZE_BLOCK | DIRDB_SYNCHRONIZE_DRAIN);
  1337. MakeMacroString(&pszTemp, pValue);
  1338. AddProduceDependency(DirDB, pszTemp);
  1339. break;
  1340. case SOURCES_SYNC_CONSUMES:
  1341. DirDB->DirFlags |= DIRDB_SYNC_CONSUMES;
  1342. //Changed so that the same directory can be the consumer as well as a block...
  1343. //DirDB->DirFlags &= ~(DIRDB_SYNCHRONIZE_BLOCK | DIRDB_SYNCHRONIZE_DRAIN);
  1344. DirDB->DirFlags &= ~(DIRDB_SYNCHRONIZE_DRAIN);
  1345. MakeMacroString(&pszTemp, pValue);
  1346. AddConsumeDependency(DirDB, pszTemp);
  1347. break;
  1348. case SOURCES_PASS0_BINPLACE:
  1349. DirDB->DirFlags |= DIRDB_PASS0NEEDED;
  1350. break;
  1351. case SOURCES_PASS1_LINK:
  1352. DirDB->DirFlags &= ~DIRDB_LINKNEEDED;
  1353. break;
  1354. }
  1355. }
  1356. SaveAndFreeMacro:
  1357. SaveMacro(TextLine, pValue);
  1358. // Make sure we cleanup from the SplitMacro call at the top.
  1359. FreeString(&TextLine, MT_DIRSTRING);
  1360. }
  1361. void
  1362. ReadProjectsInfo(
  1363. DIRREC *DirDB,
  1364. DIRSUP *pds
  1365. )
  1366. {
  1367. FILE *FileHandle;
  1368. LPSTR TextLine, pBackSlash, pszProject;
  1369. BOOL Found;
  1370. char pszProjectMkPath[DB_MAX_PATH_LENGTH];
  1371. char path[DB_MAX_PATH_LENGTH];
  1372. // First load project.mk for this project.
  1373. strcpy(pszProjectMkPath, DirDB->Name);
  1374. strcpy(path, pszProjectMkPath);
  1375. strcat(path, "\\project.mk");
  1376. Found = !_access(path, 0);
  1377. while (!Found && strlen(pszProjectMkPath)) {
  1378. pBackSlash=strrchr(pszProjectMkPath, '\\');
  1379. if (pBackSlash) {
  1380. *pBackSlash = '\0';
  1381. } else {
  1382. return;
  1383. }
  1384. strcpy(path, pszProjectMkPath);
  1385. strcat(path, "\\project.mk");
  1386. Found = !_access(path, 0);
  1387. }
  1388. if (!Found) {
  1389. return;
  1390. }
  1391. if (!OpenFilePush(pszProjectMkPath, "project.mk", "#", &FileHandle)) {
  1392. return;
  1393. }
  1394. SaveMacro("_PROJECT_MK_PATH", pszProjectMkPath);
  1395. while ((TextLine = ReadLine(FileHandle)) != NULL) {
  1396. ProcessSourcesFileLine(DirDB, pds, TextLine, -1);
  1397. }
  1398. CloseReadFile(NULL);
  1399. // Load the optional myproject.mk
  1400. if (OpenFilePush(pszProjectMkPath, "myproject.mk", "#", &FileHandle)) {
  1401. while ((TextLine = ReadLine(FileHandle)) != NULL) {
  1402. ProcessSourcesFileLine(DirDB, pds, TextLine, -1);
  1403. }
  1404. CloseReadFile(NULL);
  1405. }
  1406. // Then load ntmakeenv\projects.inc to get the other magic macro names.
  1407. if (!OpenFilePush(getenv("NTMAKEENV"), "projects.inc", "#", &FileHandle)) {
  1408. return;
  1409. }
  1410. while ((TextLine = ReadLine(FileHandle)) != NULL) {
  1411. ProcessSourcesFileLine(DirDB, pds, TextLine, -1);
  1412. }
  1413. CloseReadFile(NULL);
  1414. }
  1415. //+---------------------------------------------------------------------------
  1416. //
  1417. // Function: ReadSourcesFile
  1418. //
  1419. // Synopsis: Parses the sources files (common and platform specific)
  1420. //
  1421. // Arguments: [DirDB] -- Directory containing sources file
  1422. // [pds] -- Supplementary info on directory
  1423. // [pDateTimeSources] -- Timestamp of Sources file
  1424. //
  1425. // Returns: TRUE if read successfully
  1426. //
  1427. //----------------------------------------------------------------------------
  1428. #define SAVE_STATIC_MACRO(MacroName, InitialValue) \
  1429. { \
  1430. static char sz[] = InitialValue; \
  1431. SaveMacro(MacroName, sz); \
  1432. } \
  1433. BOOL
  1434. ReadSourcesFile(DIRREC *DirDB, DIRSUP *pds, ULONG *pDateTimeSources)
  1435. {
  1436. FILE *InFileHandle;
  1437. LPSTR p, TextLine;
  1438. UINT i;
  1439. int iTarget;
  1440. ULONG DateTime;
  1441. char path[DB_MAX_PATH_LENGTH];
  1442. char temp[DB_MAX_PATH_LENGTH];
  1443. memset(pds, 0, sizeof(*pds));
  1444. pds->fNoTarget=FALSE;
  1445. assert(DirDB->TargetPath == NULL);
  1446. assert(DirDB->TargetPathLib == NULL);
  1447. assert(DirDB->TargetName == NULL);
  1448. assert(DirDB->TargetExt == NULL);
  1449. assert(DirDB->KernelTest == NULL);
  1450. assert(DirDB->UserAppls == NULL);
  1451. assert(DirDB->UserTests == NULL);
  1452. assert(DirDB->NTTargetFile0 == NULL);
  1453. assert(DirDB->Pch == NULL);
  1454. assert(DirDB->PchObj == NULL);
  1455. assert(cMacro == 0);
  1456. *pDateTimeSources = 0;
  1457. //
  1458. // Read the information in each of the target specific directories
  1459. // and simulate concatenation of all of the sources files.
  1460. //
  1461. // Possible sources files are read from DirDB->Name | target-source
  1462. // and DirDb->Name | ..\target-source.
  1463. //
  1464. // iTarget values, and the corresponding files processed are:
  1465. // -1 sources.
  1466. // 0 PossibleTargetMachines[0]\sources.
  1467. // 1 ..\PossibleTargetMachines[0]\sources.
  1468. // 2 PossibleTargetMachines[1]\sources.
  1469. // 3 ..\PossibleTargetMachines[1]\sources.
  1470. // 4 PossibleTargetMachines[2]\sources.
  1471. // 5 ..\PossibleTargetMachines[2]\sources.
  1472. SaveMacro("MAKEDIR", DirDB->Name);
  1473. SaveMacro("SDK_LIB_DEST", pszSdkLibDest);
  1474. SaveMacro("DDK_LIB_DEST", pszDdkLibDest);
  1475. SaveMacro("PUBLIC_INTERNAL_PATH", pszPublicInternalPath);
  1476. // Use the default architecture for now
  1477. SaveMacro("TARGET_DIRECTORY", TargetMachines[0]->SourceDirectory);
  1478. SetObjDir(FALSE);
  1479. SaveMacro("_OBJ_DIR", pszObjDir);
  1480. // Define a default CONDITIONAL_INCLUDES line to deal with the mac hdrs in windows/rpc/ole32.h.
  1481. MakeMacroString(&pds->ConditionalIncludes, "winwlm.h rpcmac.h rpcerr.h macapi.h macname1.h macname2.h macocidl.h macpub.h macwin32.h");
  1482. // Before processing the sources file, see if there's a projects.mk in the tree.
  1483. ReadProjectsInfo(DirDB, pds);
  1484. SAVE_STATIC_MACRO("PROJECT_PUBLIC_PATH", "$(PUBLIC_INTERNAL_PATH)\\$(_PROJECT_)");
  1485. SAVE_STATIC_MACRO("PROJECT_INC_PATH", "$(PROJECT_PUBLIC_PATH)\\inc");
  1486. strcpy(temp,"$(PROJECT_ROOT)\\inc;$(PROJECT_ROOT)\\inc\\$(O);$(PROJECT_INC_PATH)");
  1487. MakeMacroString(&pds->NTIncludePath, temp);
  1488. for (iTarget = -1; iTarget < 2*MAX_TARGET_MACHINES; iTarget++) {
  1489. path[0] = '\0';
  1490. if (iTarget >= 0) {
  1491. if (iTarget & 1) {
  1492. strcat(path, "..\\");
  1493. }
  1494. strcat(path, PossibleTargetMachines[iTarget/2]->SourceDirectory);
  1495. strcat(path, "\\");
  1496. }
  1497. strcat(path, "sources");
  1498. if (!OpenFilePush(DirDB->Name, path, "#", &InFileHandle)) {
  1499. if (iTarget == -1) {
  1500. FreeMacros();
  1501. return (FALSE);
  1502. }
  1503. continue; // skip non-existent subordinate sources files
  1504. }
  1505. if (DEBUG_1) {
  1506. BuildMsg(
  1507. " Scanning%s file %s\r\n",
  1508. iTarget >= 0 ? " subordinate" : "",
  1509. FormatPathName(DirDB->Name, path));
  1510. }
  1511. // Update per-target macros.
  1512. if (iTarget < 0) {
  1513. SaveMacro("TARGET_DIRECTORY",
  1514. TargetMachines[0]->SourceDirectory);
  1515. SaveMacro("O", TargetMachines[0]->
  1516. ObjectDirectory[iObjectDir]);
  1517. } else {
  1518. SaveMacro("TARGET_DIRECTORY",
  1519. PossibleTargetMachines[iTarget/2]->SourceDirectory);
  1520. SaveMacro("O", PossibleTargetMachines[iTarget/2]->
  1521. ObjectDirectory[iObjectDir]);
  1522. }
  1523. SAVE_STATIC_MACRO("SDK_LIB_PATH", "$(SDK_LIB_DEST)\\$(TARGET_DIRECTORY)");
  1524. SAVE_STATIC_MACRO("PROJECT_LIB_PATH", "$(PROJECT_PUBLIC_PATH)\\lib\\$(TARGET_DIRECTORY)");
  1525. DirDB->DirFlags |= DIRDB_SOURCESREAD;
  1526. while ((TextLine = ReadLine(InFileHandle)) != NULL) {
  1527. ProcessSourcesFileLine(DirDB, pds, TextLine, iTarget);
  1528. }
  1529. // Subordinate files close themselves at EOF. Timestamps
  1530. // are propagated in CloseReadFile so the primary
  1531. // file's timestamp is automatically updated.
  1532. }
  1533. // Close the primary file.
  1534. DateTime = CloseReadFile(NULL);
  1535. if (*pDateTimeSources < DateTime) {
  1536. *pDateTimeSources = DateTime; // keep newest timestamp
  1537. }
  1538. if (!pds->fNoTarget && (DirDB->TargetPath == NULL)) {
  1539. strcpy(path, "sources");
  1540. SetupReadFile(DirDB->Name, path, "#", &InFileHandle);
  1541. BuildError(
  1542. "Unknown TARGETPATH value\r\n",
  1543. NULL);
  1544. CloseReadFile(NULL);
  1545. }
  1546. FreeMacros();
  1547. if (fChicagoProduct) {
  1548. DirDB->DirFlags |= DIRDB_CHICAGO_INCLUDES;
  1549. }
  1550. //
  1551. // Directory has pass0 files in it (.idl, .mc, .asn, etc), check to make
  1552. // sure they specified where the generated files should go. Default to the
  1553. // obj subdirectories if they didn't. These always need to be non-null.
  1554. //
  1555. if (!pds->PassZeroHdrDir) {
  1556. MakeString(&pds->PassZeroHdrDir, ".", TRUE, MT_DIRSTRING);
  1557. }
  1558. if (!pds->PassZeroSrcDir1) {
  1559. MakeString(&pds->PassZeroSrcDir1, ".", TRUE, MT_DIRSTRING);
  1560. }
  1561. if (!pds->PassZeroSrcDir2)
  1562. MakeString(&pds->PassZeroSrcDir2, pds->PassZeroSrcDir1, TRUE, MT_DIRSTRING);
  1563. if (DirDB->UserTests != NULL) {
  1564. _strlwr(DirDB->UserTests);
  1565. }
  1566. if (DirDB->UserAppls != NULL) {
  1567. if (DirDB->UserTests != NULL || strchr(DirDB->UserAppls, '*') != NULL) {
  1568. DirDB->DirFlags |= DIRDB_FORCELINK; // multiple targets
  1569. }
  1570. }
  1571. PostProcessSources(DirDB, pds);
  1572. if (DEBUG_1) {
  1573. PrintDirDB(DirDB, 1|2);
  1574. PrintDirSupData(pds);
  1575. PrintDirDB(DirDB, 4);
  1576. }
  1577. pds->DateTimeSources = *pDateTimeSources;
  1578. return (TRUE);
  1579. }
  1580. #undef SAVE_STATIC_MACRO
  1581. //+---------------------------------------------------------------------------
  1582. //
  1583. // Function: PostProcessSources
  1584. //
  1585. // Synopsis: Scan the files in the given directory and add files to the
  1586. // directory's list of source files (SOURCEREC), including PCH
  1587. // files, UMTEST files, etc.
  1588. //
  1589. // Arguments: [pdr] -- Directory to process
  1590. // [pds] -- Directory supplemental information
  1591. //
  1592. //----------------------------------------------------------------------------
  1593. void
  1594. PostProcessSources(DIRREC *pdr, DIRSUP *pds)
  1595. {
  1596. PFILEREC FileDB, *FileDBNext;
  1597. char path[DB_MAX_PATH_LENGTH];
  1598. LPSTR p, p1;
  1599. UINT i;
  1600. for (i = 0; i < MAX_TARGET_MACHINES + 2; i++) {
  1601. if (pds->SourcesVariables[i] != NULL) {
  1602. CrackSources(pdr, pds, i);
  1603. }
  1604. }
  1605. FileDBNext = &pdr->Files;
  1606. while (FileDB = *FileDBNext) {
  1607. if (pds->PchInclude && strcmp(FileDB->Name, pds->PchInclude) == 0) {
  1608. InsertSourceDB(&pds->psrSourcesList[0], FileDB, 0, SOURCEDB_PCH);
  1609. if (DEBUG_1) {
  1610. BuildMsg("Adding PCH file to Sources List: %s.\r\n", FileDB->Name);
  1611. }
  1612. }
  1613. if ((FileDB->FileFlags & (FILEDB_SOURCE | FILEDB_OBJECTS_LIST)) ==
  1614. FILEDB_SOURCE) {
  1615. p = FileDB->Name;
  1616. p1 = path;
  1617. while (*p != '\0' && *p != '.') {
  1618. *p1++ = *p++;
  1619. }
  1620. *p1 = '\0';
  1621. _strlwr(path);
  1622. if (pdr->KernelTest != NULL &&
  1623. !strcmp(path, pdr->KernelTest)) {
  1624. FileDB->FileFlags |= FILEDB_OBJECTS_LIST;
  1625. } else
  1626. if (pdr->UserAppls != NULL &&
  1627. (p = strstr(pdr->UserAppls, path)) &&
  1628. (p == pdr->UserAppls || p[-1] == '*' || p[-1] == ' ')) {
  1629. FileDB->FileFlags |= FILEDB_OBJECTS_LIST;
  1630. } else
  1631. if (pdr->UserTests != NULL &&
  1632. (p = strstr(pdr->UserTests, path)) &&
  1633. (p == pdr->UserTests || p[-1] == '*' || p[-1] == ' ')) {
  1634. FileDB->FileFlags |= FILEDB_OBJECTS_LIST;
  1635. }
  1636. if (FileDB->FileFlags & FILEDB_OBJECTS_LIST) {
  1637. InsertSourceDB(&pds->psrSourcesList[0], FileDB, 0, 0);
  1638. }
  1639. }
  1640. FileDBNext = &FileDB->Next;
  1641. }
  1642. return;
  1643. }
  1644. //+---------------------------------------------------------------------------
  1645. //
  1646. // Function: ReadDirsFile
  1647. //
  1648. // Synopsis: Parse the DIRS file
  1649. //
  1650. // Arguments: [DirDB] -- Directory to look in
  1651. //
  1652. // Returns: TRUE if parsed
  1653. //
  1654. // Notes: The existence of a file named 'mydirs' or the name of the
  1655. // target specific dirs will override the normal 'dirs' file.
  1656. //
  1657. //----------------------------------------------------------------------------
  1658. BOOL
  1659. ReadDirsFile(
  1660. PDIRREC DirDB
  1661. )
  1662. {
  1663. FILE *InFileHandle;
  1664. LPSTR TextLine, pValue;
  1665. LPSTR apszDirs[] = { "mydirs", NULL, "dirs", NULL};
  1666. CHAR TargetName[16];
  1667. strcpy(&TargetName[0], pszTargetDirs);
  1668. strcat(&TargetName[0], ".");
  1669. apszDirs[1] = &TargetName[0];
  1670. for (ppCurrentDirsFileName = apszDirs;
  1671. *ppCurrentDirsFileName != NULL;
  1672. ppCurrentDirsFileName++) {
  1673. if (SetupReadFile(DirDB->Name, *ppCurrentDirsFileName, "#", &InFileHandle)) {
  1674. break;
  1675. }
  1676. }
  1677. if (*ppCurrentDirsFileName == NULL || !InFileHandle) {
  1678. FreeMacros();
  1679. return (FALSE);
  1680. }
  1681. if (fFirstScan && (ppCurrentDirsFileName <= &apszDirs[1])) {
  1682. BuildMsg("Using .\\%s instead of DIRS...\r\n",
  1683. FormatPathName(DirDB->Name, *ppCurrentDirsFileName));
  1684. }
  1685. if (DEBUG_1) {
  1686. BuildMsg(
  1687. " Scanning file %s\r\n",
  1688. FormatPathName(DirDB->Name, *ppCurrentDirsFileName));
  1689. }
  1690. assert(cMacro == 0);
  1691. while ((TextLine = ReadLine(InFileHandle)) != NULL) {
  1692. if ((pValue = SplitMacro(&TextLine)) != NULL) {
  1693. SaveMacro(TextLine, pValue);
  1694. FreeString(&TextLine, MT_DIRSTRING);
  1695. }
  1696. }
  1697. CloseReadFile(NULL);
  1698. if ((pValue = FindMacro("DIRS")) != NULL) {
  1699. MarkDirNames(DirDB, pValue, TRUE);
  1700. }
  1701. if ((pValue = FindMacro("OPTIONAL_DIRS")) != NULL) {
  1702. MarkDirNames(DirDB, pValue, BuildAllOptionalDirs);
  1703. }
  1704. if ((FindMacro("SYNCHRONIZE_DRAIN")) != NULL) {
  1705. if (!fIgnoreSync) {
  1706. DirDB->DirFlags |= DIRDB_SYNCHRONIZE_DRAIN;
  1707. }
  1708. }
  1709. FreeMacros();
  1710. return ( TRUE );
  1711. }
  1712. //
  1713. // Debugging and Utility Functions
  1714. //
  1715. VOID
  1716. PrintDirSupData(DIRSUP *pds)
  1717. {
  1718. int i;
  1719. if (pds->LocalIncludePath != NULL) {
  1720. BuildMsgRaw(" LocalIncludePath: %s\r\n", pds->LocalIncludePath);
  1721. }
  1722. if (pds->UserIncludePath != NULL) {
  1723. BuildMsgRaw(" UserIncludePath: %s\r\n", pds->UserIncludePath);
  1724. }
  1725. if (pds->LastIncludePath != NULL) {
  1726. BuildMsgRaw(" LastIncludePath: %s\r\n", pds->LastIncludePath);
  1727. }
  1728. if (pds->TestType != NULL) {
  1729. BuildMsgRaw(" TestType: %s\r\n", pds->TestType);
  1730. }
  1731. if (pds->PchIncludeDir != NULL) {
  1732. BuildMsgRaw(" PchIncludeDir: %s\r\n", pds->PchIncludeDir);
  1733. }
  1734. if (pds->PchInclude != NULL) {
  1735. BuildMsgRaw(" PchInclude: %s\r\n", pds->PchInclude);
  1736. }
  1737. if (pds->PchTargetDir != NULL) {
  1738. BuildMsgRaw(" PchTargetDir: %s\r\n", pds->PchTargetDir);
  1739. }
  1740. if (pds->PchTarget != NULL) {
  1741. BuildMsgRaw(" PchTarget: %s\r\n", pds->PchTarget);
  1742. }
  1743. if (pds->ConditionalIncludes != NULL) {
  1744. BuildMsgRaw(" ConditionalIncludes: %s\r\n", pds->ConditionalIncludes);
  1745. }
  1746. for (i = 0; i < MAX_TARGET_MACHINES + 2; i++) {
  1747. if (pds->SourcesVariables[i] != NULL) {
  1748. BuildMsgRaw(
  1749. " SourcesVariables[%d]: %s\r\n",
  1750. i,
  1751. pds->SourcesVariables[i]);
  1752. }
  1753. if (pds->psrSourcesList[i] != NULL) {
  1754. BuildMsgRaw(" SourcesList[%d]:\r\n", i);
  1755. PrintSourceDBList(pds->psrSourcesList[i], i);
  1756. }
  1757. }
  1758. }
  1759. VOID
  1760. FreeDirSupData(DIRSUP *pds)
  1761. {
  1762. int i;
  1763. if (pds->LocalIncludePath != NULL) {
  1764. FreeMem(&pds->LocalIncludePath, MT_DIRSTRING);
  1765. }
  1766. if (pds->UserIncludePath != NULL) {
  1767. FreeMem(&pds->UserIncludePath, MT_DIRSTRING);
  1768. }
  1769. if (pds->LastIncludePath != NULL) {
  1770. FreeMem(&pds->LastIncludePath, MT_DIRSTRING);
  1771. }
  1772. if (pds->NTIncludePath != NULL) {
  1773. FreeMem(&pds->NTIncludePath, MT_DIRSTRING);
  1774. }
  1775. if (pds->TestType != NULL) {
  1776. FreeMem(&pds->TestType, MT_DIRSTRING);
  1777. }
  1778. if (pds->PchInclude != NULL) {
  1779. FreeMem(&pds->PchInclude, MT_DIRSTRING);
  1780. }
  1781. if (pds->PchIncludeDir != NULL) {
  1782. FreeMem(&pds->PchIncludeDir, MT_DIRSTRING);
  1783. }
  1784. if (pds->PchTargetDir != NULL) {
  1785. FreeMem(&pds->PchTargetDir, MT_DIRSTRING);
  1786. }
  1787. if (pds->PchTarget != NULL) {
  1788. FreeMem(&pds->PchTarget, MT_DIRSTRING);
  1789. }
  1790. if (pds->ConditionalIncludes != NULL) {
  1791. FreeMem(&pds->ConditionalIncludes, MT_DIRSTRING);
  1792. }
  1793. if (pds->PassZeroHdrDir != NULL) {
  1794. FreeMem(&pds->PassZeroHdrDir, MT_DIRSTRING);
  1795. }
  1796. if (pds->PassZeroSrcDir1 != NULL) {
  1797. FreeMem(&pds->PassZeroSrcDir1, MT_DIRSTRING);
  1798. }
  1799. if (pds->PassZeroSrcDir2 != NULL) {
  1800. FreeMem(&pds->PassZeroSrcDir2, MT_DIRSTRING);
  1801. }
  1802. for (i = 0; i < MAX_TARGET_MACHINES + 2; i++) {
  1803. if (pds->SourcesVariables[i] != NULL) {
  1804. FreeMem(&pds->SourcesVariables[i], MT_DIRSTRING);
  1805. }
  1806. while (pds->psrSourcesList[i] != NULL) {
  1807. FreeSourceDB(&pds->psrSourcesList[i]);
  1808. }
  1809. }
  1810. }
  1811. VOID
  1812. FreeDirData(DIRREC *pdr)
  1813. {
  1814. if (pdr->TargetPath != NULL) {
  1815. FreeMem(&pdr->TargetPath, MT_DIRSTRING);
  1816. }
  1817. if (pdr->TargetPathLib != NULL) {
  1818. FreeMem(&pdr->TargetPathLib, MT_DIRSTRING);
  1819. }
  1820. if (pdr->TargetName != NULL) {
  1821. FreeMem(&pdr->TargetName, MT_DIRSTRING);
  1822. }
  1823. if (pdr->TargetExt != NULL) {
  1824. FreeMem(&pdr->TargetExt, MT_DIRSTRING);
  1825. }
  1826. if (pdr->KernelTest != NULL) {
  1827. FreeMem(&pdr->KernelTest, MT_DIRSTRING);
  1828. }
  1829. if (pdr->UserAppls != NULL) {
  1830. FreeMem(&pdr->UserAppls, MT_DIRSTRING);
  1831. }
  1832. if (pdr->UserTests != NULL) {
  1833. FreeMem(&pdr->UserTests, MT_DIRSTRING);
  1834. }
  1835. if (pdr->NTTargetFile0 != NULL) {
  1836. FreeMem(&pdr->NTTargetFile0, MT_DIRSTRING);
  1837. }
  1838. if (pdr->Pch != NULL) {
  1839. FreeMem(&pdr->Pch, MT_DIRSTRING);
  1840. }
  1841. if (pdr->PchObj != NULL) {
  1842. FreeMem(&pdr->PchObj, MT_DIRSTRING);
  1843. }
  1844. if (pdr->pds != NULL) {
  1845. FreeDirSupData(pdr->pds);
  1846. FreeMem(&pdr->pds, MT_DIRSUP);
  1847. pdr->pds = NULL;
  1848. }
  1849. }
  1850. //+---------------------------------------------------------------------------
  1851. //
  1852. // Function: MarkDirNames
  1853. //
  1854. // Synopsis: Parses a DIRS= or OPTIONAL_DIRS line and marks the directories
  1855. // appropriately.
  1856. //
  1857. // Arguments: [DirDB] -- Directory containing DIRS file
  1858. // [TextLine] -- DIRS= or OPTIONAL_DIRS= line
  1859. // [Required] -- Indicates if directories are optional or not.
  1860. //
  1861. //----------------------------------------------------------------------------
  1862. VOID
  1863. MarkDirNames(PDIRREC DirDB, LPSTR TextLine, BOOL Required)
  1864. {
  1865. UINT i;
  1866. LPSTR p, token;
  1867. PFILEREC FileDB, *FileDBNext;
  1868. char dirbuf[DB_MAX_PATH_LENGTH];
  1869. ULONG DirInclude;
  1870. AssertPathString(TextLine);
  1871. while (SplitToken(dirbuf, '*', &TextLine)) {
  1872. // Assume all platforms are included for this dir.
  1873. DirInclude = DIR_INCLUDE_ALL;
  1874. for (p = dirbuf; *p != '\0'; p++) {
  1875. if ( dirbuf != p && *p == '{' ) {
  1876. // An explicit include path was listed.
  1877. DirInclude = DIR_INCLUDE_NONE;
  1878. *p = '\0';
  1879. token = strtok(p+1, ",}");
  1880. while (token) {
  1881. if (!_stricmp(token, "X86") ||
  1882. !_stricmp(token, "I386") ||
  1883. !_stricmp(token, "386")) {
  1884. DirInclude |= DIR_INCLUDE_X86;
  1885. } else if (!_stricmp(token, "32") ||
  1886. !_stricmp(token, "Win32")) {
  1887. DirInclude |= DIR_INCLUDE_WIN32;
  1888. } else if (!_stricmp(token, "64") ||
  1889. !_stricmp(token, "Win64")) {
  1890. DirInclude |= DIR_INCLUDE_WIN64;
  1891. } else if (!_stricmp(token, "IA64")) {
  1892. DirInclude |= DIR_INCLUDE_IA64;
  1893. } else if (!_stricmp(token, "AMD64")) {
  1894. DirInclude |= DIR_INCLUDE_AMD64;
  1895. } else if (!_stricmp(token, "RISC")) {
  1896. DirInclude |= DIR_INCLUDE_RISC;
  1897. } else if (!_stricmp(token, "ARM")) {
  1898. DirInclude |= DIR_INCLUDE_ARM;
  1899. }
  1900. token = strtok(NULL, ",}");
  1901. }
  1902. break;
  1903. } else {
  1904. if (!iscsym(*p) && *p != '.' && *p != '-' ) {
  1905. BuildError(
  1906. "%s: ignoring bad subdirectory: %s\r\n",
  1907. DirDB->Name,
  1908. dirbuf);
  1909. p = NULL;
  1910. break;
  1911. }
  1912. }
  1913. }
  1914. if (!(DirInclude & TargetMachines[0]->DirIncludeMask)) {
  1915. continue;
  1916. }
  1917. if (p != NULL) {
  1918. if (!Required) {
  1919. for (i = 0; i < CountOptionalDirs; i++) {
  1920. if (!strcmp(dirbuf, OptionalDirs[i])) {
  1921. OptionalDirsUsed[i] = TRUE;
  1922. break;
  1923. }
  1924. }
  1925. if (i >= CountOptionalDirs) {
  1926. p = NULL;
  1927. }
  1928. } else {
  1929. for (i = 0; i < CountExcludeDirs; i++) {
  1930. if (!strcmp(dirbuf, ExcludeDirs[i])) {
  1931. ExcludeDirsUsed[i] = TRUE;
  1932. p = NULL;
  1933. break;
  1934. }
  1935. }
  1936. }
  1937. }
  1938. if (p != NULL) {
  1939. if ((fQuicky || fSemiQuicky) && (!fQuickZero)) {
  1940. FileDB = InsertFileDB(
  1941. DirDB,
  1942. dirbuf,
  1943. 0,
  1944. FILE_ATTRIBUTE_DIRECTORY,
  1945. 0);
  1946. if (FileDB != NULL) {
  1947. FileDB->SubDirIndex = ++DirDB->CountSubDirs;
  1948. }
  1949. } else {
  1950. FileDBNext = &DirDB->Files;
  1951. while (FileDB = *FileDBNext) {
  1952. if (FileDB->FileFlags & FILEDB_DIR) {
  1953. if (!strcmp(dirbuf, FileDB->Name)) {
  1954. FileDB->SubDirIndex = ++DirDB->CountSubDirs;
  1955. break;
  1956. }
  1957. }
  1958. FileDBNext = &FileDB->Next;
  1959. }
  1960. if (FileDB == NULL) {
  1961. BuildError(
  1962. "%s found in %s, is not a subdirectory of %s\r\n",
  1963. dirbuf,
  1964. FormatPathName(DirDB->Name, *ppCurrentDirsFileName),
  1965. DirDB->Name);
  1966. }
  1967. }
  1968. }
  1969. }
  1970. }
  1971. VOID
  1972. StartElapsedTime(VOID)
  1973. {
  1974. // we don't want to check for fElapsedTime since if we want XML file, we need it anyway
  1975. // and single GetTickCount() call is not a perf hit
  1976. if (StartTime == 0) {
  1977. StartTime = GetTickCount();
  1978. }
  1979. }
  1980. VOID
  1981. StartDirectoryElapsedTime(VOID)
  1982. {
  1983. DirectoryStartTime = GetTickCount();
  1984. }
  1985. VOID
  1986. PrintElapsedTime(VOID)
  1987. {
  1988. DWORD ElapsedTime;
  1989. DWORD ElapsedHours;
  1990. DWORD ElapsedMinutes;
  1991. DWORD ElapsedSeconds;
  1992. DWORD ElapsedMilliseconds;
  1993. CONSOLE_SCREEN_BUFFER_INFO csbi;
  1994. GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &csbi);
  1995. if (fPrintElapsed) {
  1996. ElapsedTime = GetTickCount() - StartTime;
  1997. ElapsedHours = ElapsedTime/(1000 * 60 * 60);
  1998. ElapsedTime = ElapsedTime % (1000 * 60 * 60);
  1999. ElapsedMinutes = ElapsedTime/(1000 * 60);
  2000. ElapsedTime = ElapsedTime % (1000 * 60);
  2001. ElapsedSeconds = ElapsedTime/1000;
  2002. ElapsedMilliseconds = ElapsedTime % 1000;
  2003. BuildColorMsg(
  2004. COLOR_STATUS,
  2005. "Elapsed time [%d:%02d:%02d.%03d]\r\n",
  2006. ElapsedHours,
  2007. ElapsedMinutes,
  2008. ElapsedSeconds,
  2009. ElapsedMilliseconds);
  2010. LogMsg(
  2011. "Elapsed time [%d:%02d:%02d.%03d]%s\r\n",
  2012. ElapsedHours,
  2013. ElapsedMinutes,
  2014. ElapsedSeconds,
  2015. ElapsedMilliseconds,
  2016. szAsterisks);
  2017. }
  2018. }
  2019. LPSTR
  2020. FormatElapsedTime(DWORD dwStartTime)
  2021. {
  2022. static char FormatElapsedTimeBuffer[16];
  2023. DWORD ElapsedTime;
  2024. DWORD ElapsedHours;
  2025. DWORD ElapsedMinutes;
  2026. DWORD ElapsedSeconds;
  2027. DWORD ElapsedMilliseconds;
  2028. ElapsedTime = GetTickCount() - dwStartTime;
  2029. ElapsedHours = ElapsedTime/(1000 * 60 * 60);
  2030. ElapsedTime = ElapsedTime % (1000 * 60 * 60);
  2031. ElapsedMinutes = ElapsedTime/(1000 * 60);
  2032. ElapsedTime = ElapsedTime % (1000 * 60);
  2033. ElapsedSeconds = ElapsedTime/1000;
  2034. ElapsedMilliseconds = ElapsedTime % 1000;
  2035. sprintf(
  2036. FormatElapsedTimeBuffer,
  2037. "%d:%02d:%02d.%03d",
  2038. ElapsedHours,
  2039. ElapsedMinutes,
  2040. ElapsedSeconds,
  2041. ElapsedMilliseconds);
  2042. return ( FormatElapsedTimeBuffer );
  2043. }
  2044. LPSTR
  2045. FormatCurrentDateTime()
  2046. {
  2047. static char FormatCurrentDateTimeBuffer[18];
  2048. SYSTEMTIME st;
  2049. GetLocalTime(&st);
  2050. sprintf(
  2051. FormatCurrentDateTimeBuffer,
  2052. "%04d%02d%02d%02d%02d%02d%03d",
  2053. st.wYear, st.wMonth, st.wDay,
  2054. st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
  2055. return ( FormatCurrentDateTimeBuffer );
  2056. }