mirror of https://github.com/lianthony/NT4.0
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.
1628 lines
52 KiB
1628 lines
52 KiB
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1992 - 1993.
|
|
//
|
|
// File: buildsrc.c
|
|
//
|
|
// Contents: Functions used to process SOURCES and DIRS files
|
|
//
|
|
// History: 16-May-89 SteveWo Created
|
|
// 26-Jul-94 LyleC Split out from buildmak.c
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "build.h"
|
|
|
|
//
|
|
// Definitions used by the macro functions
|
|
//
|
|
|
|
#define LPAREN '('
|
|
#define RPAREN ')'
|
|
|
|
#define CMACROMAX 100 // maximum unique macros per sources/dirs file
|
|
|
|
typedef struct _MACRO {
|
|
LPSTR pszValue;
|
|
UCHAR szName[1];
|
|
} MACRO;
|
|
|
|
|
|
MACRO *apMacro[CMACROMAX];
|
|
UINT cMacro = 0;
|
|
|
|
LPSTR *ppCurrentDirsFileName;
|
|
DWORD StartTime;
|
|
|
|
#define SOURCES_TARGETNAME 0
|
|
#define SOURCES_TARGETPATH 1
|
|
#define SOURCES_TARGETTYPE 2
|
|
#define SOURCES_TARGETEXT 3
|
|
#define SOURCES_INCLUDES 4
|
|
#define SOURCES_NTTEST 5
|
|
#define SOURCES_UMTYPE 6
|
|
#define SOURCES_UMTEST 7
|
|
#define SOURCES_OPTIONAL_UMTEST 8
|
|
#define SOURCES_UMAPPL 9
|
|
#define SOURCES_UMAPPLEXT 10
|
|
#define SOURCES_NTTARGETFILE0 11
|
|
#define SOURCES_NTTARGETFILES 12
|
|
#define SOURCES_PRECOMPILED_INCLUDE 13
|
|
#define SOURCES_PRECOMPILED_PCH 14
|
|
#define SOURCES_PRECOMPILED_OBJ 15
|
|
#define SOURCES_PRECOMPILED_TARGET 16
|
|
#define SOURCES_CAIRO_PRODUCT 17
|
|
#define SOURCES_CHICAGO_PRODUCT 18
|
|
#define SOURCES_CONDITIONAL_INCLUDES 19
|
|
#define SOURCES_SYNCHRONIZE_BLOCK 20
|
|
#define SOURCES_SYNCHRONIZE_DRAIN 21
|
|
#define SOURCES_PASS0_SOURCEDIR 22
|
|
#define SOURCES_PASS0_HEADERDIR 23
|
|
#define SOURCES_MIDL_UUIDDIR 24
|
|
#define SOURCES_PASS0_CLIENTDIR 25
|
|
#define SOURCES_PASS0_SERVERDIR 26
|
|
#define SOURCES_IDLTYPE 27
|
|
#define SOURCES_SOURCES_OPTIONS 28
|
|
#define SOURCES_MFC_INCLUDES 29
|
|
#define SOURCES_SDK_INC_PATH 30
|
|
#define SOURCES_CRT_INC_PATH 31
|
|
#define SOURCES_OAK_INC_PATH 32
|
|
#define SOURCES_CHECKED_ALT_DIR 33
|
|
|
|
LPSTR RelevantSourcesMacros[] = {
|
|
"TARGETNAME",
|
|
"TARGETPATH",
|
|
"TARGETTYPE",
|
|
"TARGETEXT",
|
|
"INCLUDES",
|
|
"NTTEST",
|
|
"UMTYPE",
|
|
"UMTEST",
|
|
"OPTIONAL_UMTEST",
|
|
"UMAPPL",
|
|
"UMAPPLEXT",
|
|
"NTTARGETFILE0",
|
|
"NTTARGETFILES",
|
|
"PRECOMPILED_INCLUDE",
|
|
"PRECOMPILED_PCH",
|
|
"PRECOMPILED_OBJ",
|
|
"PRECOMPILED_TARGET",
|
|
"CAIRO_PRODUCT",
|
|
"CHICAGO_PRODUCT",
|
|
"CONDITIONAL_INCLUDES",
|
|
"SYNCHRONIZE_BLOCK",
|
|
"SYNCHRONIZE_DRAIN",
|
|
"PASS0_SOURCEDIR",
|
|
"PASS0_HEADERDIR",
|
|
"MIDL_UUIDDIR",
|
|
"PASS0_CLIENTDIR",
|
|
"PASS0_SERVERDIR",
|
|
"IDL_TYPE",
|
|
"SOURCES_OPTIONS",
|
|
"MFC_INCLUDES",
|
|
"SDK_INC_PATH",
|
|
"CRT_INC_PATH",
|
|
"OAK_INC_PATH",
|
|
"CHECKED_ALT_DIR",
|
|
NULL
|
|
};
|
|
|
|
#define SOURCES_MAX \
|
|
(sizeof(RelevantSourcesMacros)/sizeof(RelevantSourcesMacros[0]) - 1)
|
|
|
|
VOID
|
|
MarkDirNames(PDIRREC DirDB, LPSTR TextLine, BOOL Required);
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CompressBlanks
|
|
//
|
|
// Synopsis: Compress multiple blank characters out of macro value, in
|
|
// place.
|
|
//
|
|
// Arguments: [psrc] -- String to compress
|
|
//
|
|
// Notes: Note that tabs, CRs, continuation lines (and their line
|
|
// breaks) have already been replaced with blanks.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
CompressBlanks(LPSTR psrc)
|
|
{
|
|
LPSTR pdst = psrc;
|
|
|
|
while (*psrc == ' ') {
|
|
psrc++; // skip leading macro value blanks
|
|
}
|
|
while (*psrc != '\0') {
|
|
if (*psrc == '#') { // stop at comment
|
|
break;
|
|
}
|
|
if ((*pdst++ = *psrc++) == ' ') {
|
|
while (*psrc == ' ') {
|
|
psrc++; // skip multiple blanks
|
|
}
|
|
}
|
|
}
|
|
*pdst = '\0'; // terminate the compressed copy
|
|
if (*--pdst == ' ') {
|
|
*pdst = '\0'; // trim trailing macro value blanks
|
|
}
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: GetBaseDir
|
|
//
|
|
// Synopsis: Return the value of BASEDIR, the base NT directory, if
|
|
// appropriate.
|
|
//
|
|
// Arguments: [pname] -- path to split
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
LPSTR
|
|
GetBaseDir(LPSTR pname)
|
|
{
|
|
if (_stricmp("BASEDIR", pname) == 0) {
|
|
return(NtRoot);
|
|
}
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FindMacro
|
|
//
|
|
// Synopsis: Returns the value of a given macro by name.
|
|
//
|
|
// Arguments: [pszName] -- Name of macro who's value is desired.
|
|
//
|
|
// Returns: String containing the value of the macro
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
LPSTR
|
|
FindMacro(LPSTR pszName)
|
|
{
|
|
MACRO **ppm;
|
|
|
|
for (ppm = apMacro; ppm < &apMacro[cMacro]; ppm++) {
|
|
if (_stricmp(pszName, (*ppm)->szName) == 0) {
|
|
return((*ppm)->pszValue);
|
|
}
|
|
}
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: SaveMacro
|
|
//
|
|
// Synopsis: Save the value of a macro
|
|
//
|
|
// Arguments: [pszName] -- Name of macro to save
|
|
// [pszValue] -- Value of macro
|
|
//
|
|
// Notes: A new string must be allocated and initialized prior to
|
|
// freeing the old string when updating a macro value.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
SaveMacro(LPSTR pszName, LPSTR pszValue)
|
|
{
|
|
MACRO **ppm;
|
|
|
|
for (ppm = apMacro; ppm < &apMacro[cMacro]; ppm++) {
|
|
if (_stricmp(pszName, (*ppm)->szName) == 0) {
|
|
break;
|
|
}
|
|
}
|
|
if (ppm == &apMacro[CMACROMAX]) {
|
|
BuildError("Macro table full, ignoring: %s = %s\n", pszName, pszValue);
|
|
return;
|
|
}
|
|
if (ppm == &apMacro[cMacro]) {
|
|
cMacro++;
|
|
AllocMem(sizeof(MACRO) + strlen(pszName), ppm, MT_MACRO);
|
|
strcpy((*ppm)->szName, pszName);
|
|
(*ppm)->pszValue = NULL;
|
|
}
|
|
MakeMacroString(&(*ppm)->pszValue, pszValue);
|
|
if (DEBUG_1) {
|
|
BuildMsg(
|
|
"SaveMacro(%s = %s)\n",
|
|
(*ppm)->szName,
|
|
(*ppm)->pszValue == NULL? "NULL" : (*ppm)->pszValue);
|
|
}
|
|
if ((*ppm)->pszValue == NULL) {
|
|
FreeMem(ppm, MT_MACRO);
|
|
*ppm = apMacro[--cMacro];
|
|
}
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FreeMacros
|
|
//
|
|
// Synopsis: Free all macros
|
|
//
|
|
// Arguments: (none)
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
FreeMacros(VOID)
|
|
{
|
|
MACRO **ppm;
|
|
|
|
for (ppm = apMacro; ppm < &apMacro[cMacro]; ppm++) {
|
|
FreeString(&(*ppm)->pszValue, MT_DIRSTRING);
|
|
FreeMem(ppm, MT_MACRO);
|
|
assert(*ppm == NULL);
|
|
}
|
|
cMacro = 0;
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: SplitMacro
|
|
//
|
|
// Synopsis: Take a string containing "MACRONAME = VALUE" and return the
|
|
// value.
|
|
//
|
|
// Arguments: [pline] -- String to parse
|
|
//
|
|
// Returns: Value of macro.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
LPSTR
|
|
SplitMacro(LPSTR pline)
|
|
{
|
|
LPSTR pvalue, p;
|
|
|
|
pvalue = NULL;
|
|
|
|
if ((p = strchr(pline, '=')) != NULL) {
|
|
pvalue = p + 1; // point past old '='
|
|
while (p > pline && p[-1] == ' ') {
|
|
p--; // point to start of trailing blanks
|
|
}
|
|
|
|
for ( ; pline < p; pline++) {
|
|
if (!iscsym(*pline)) {
|
|
return(NULL); // not a valid macro name
|
|
}
|
|
}
|
|
*p = '\0'; // trim trailing blanks & '='
|
|
CompressBlanks(pvalue);
|
|
}
|
|
return(pvalue);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: MakeMacroString
|
|
//
|
|
// Synopsis: Take a string, and expand any macros in it. (e.g.
|
|
// "$(BASEDIR)\foobar\myfile.lib" is expanded to
|
|
// "f:\nt\private\foobar\myfile.lib" if $(BASEDIR) has a value of
|
|
// "f:\nt\private".
|
|
//
|
|
// Arguments: [pp] -- Output string
|
|
// [psrc] -- Input string
|
|
//
|
|
// Returns:
|
|
//
|
|
// Notes: Any previous string value in [pp] is freed before updating it.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
MakeMacroString(LPSTR *pp, LPSTR psrc)
|
|
{
|
|
LPSTR pname, p2, pdst;
|
|
int cb;
|
|
char Buffer[4096];
|
|
|
|
pdst = Buffer;
|
|
cb = strlen(psrc);
|
|
if (cb > sizeof(Buffer) - 1) {
|
|
BuildError(
|
|
"(Fatal Error) Buffer overflow: MakeMacroString(%s)\n",
|
|
psrc);
|
|
exit(16);
|
|
}
|
|
while ((pname = strchr(psrc, '$')) != NULL &&
|
|
pname[1] == LPAREN &&
|
|
(p2 = strchr(pname, RPAREN)) != NULL) {
|
|
|
|
LPSTR pszvalue;
|
|
|
|
*pname = *p2 = '\0';
|
|
strcpy(pdst, psrc); // copy up to macro name
|
|
pdst += strlen(pdst);
|
|
*pname = '$';
|
|
pname += 2;
|
|
|
|
if ((pszvalue = FindMacro(pname)) == NULL &&
|
|
(pszvalue = getenv(pname)) == NULL &&
|
|
(pszvalue = GetBaseDir(pname)) == NULL) {
|
|
|
|
pszvalue = ""; // can't find macro name -- ignore it
|
|
}
|
|
cb += strlen(pszvalue) - 3 - strlen(pname);
|
|
assert(cb >= 0);
|
|
if (cb > sizeof(Buffer) - 1) {
|
|
BuildError(
|
|
"(Fatal Error) Internal buffer overflow: MakeMacroString(%s[%s = %s]%s)\n",
|
|
Buffer,
|
|
pname,
|
|
pszvalue,
|
|
p2 + 1);
|
|
exit(16);
|
|
}
|
|
strcpy(pdst, pszvalue); // copy expanded value
|
|
pdst += strlen(pdst);
|
|
*p2 = RPAREN;
|
|
psrc = p2 + 1;
|
|
}
|
|
strcpy(pdst, psrc); // copy rest of string
|
|
if (pdst != Buffer) {
|
|
CompressBlanks(Buffer);
|
|
}
|
|
p2 = *pp;
|
|
*pp = NULL;
|
|
if (Buffer[0] != '\0') {
|
|
MakeString(pp, Buffer, TRUE, MT_DIRSTRING);
|
|
}
|
|
if (p2 != NULL) {
|
|
FreeMem(&p2, MT_DIRSTRING);
|
|
}
|
|
return(Buffer[0] != '\0');
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: SetMacroString
|
|
//
|
|
// Synopsis: If the two macro names are the same, store the value in that
|
|
// macro
|
|
//
|
|
// Arguments: [pMacro1] -- Name of first macro
|
|
// [pMacro2] -- Name of second macro
|
|
// [pValue] -- Unexpanded value to store.
|
|
// [ppValue] -- Expanded value of macro.
|
|
//
|
|
// Returns: BOOL
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
SetMacroString(LPSTR pMacro1, LPSTR pMacro2, LPSTR pValue, LPSTR *ppValue)
|
|
{
|
|
if (_stricmp(pMacro1, pMacro2) == 0) {
|
|
MakeMacroString(ppValue, pValue);
|
|
return(TRUE); // return TRUE even if MakeMacroString stored a NULL
|
|
}
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: SplitToken
|
|
//
|
|
// Synopsis: Split the string at the given separator character or space.
|
|
//
|
|
// Arguments: [pbuf] -- First part of split string returned here.
|
|
// [chsep] -- Separator character.
|
|
// [ppstr] -- Source string to split. Becomes the second half.
|
|
//
|
|
// Returns: TRUE if the split was successful. FALSE if it wasn't split.
|
|
//
|
|
// Notes: If *ppstr = "path\filename" and chsep = '\' on input, then
|
|
// pbuf = "path" and *ppstr = "\filename" on output.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
SplitToken(LPSTR pbuf, char chsep, LPSTR *ppstr)
|
|
{
|
|
LPSTR psrc, pdst;
|
|
|
|
psrc = *ppstr;
|
|
pdst = pbuf;
|
|
//BuildError("SplitToken('%c', '%s') ==> ", chsep, psrc);
|
|
while (*psrc == chsep || *psrc == ' ') {
|
|
psrc++;
|
|
}
|
|
while (*psrc != '\0' && *psrc != chsep && *psrc != ' ') {
|
|
*pdst = *psrc++;
|
|
if (*pdst == '/') {
|
|
*pdst = '\\';
|
|
}
|
|
pdst++;
|
|
}
|
|
*pdst = '\0';
|
|
*ppstr = psrc;
|
|
//BuildErrorRaw("('%s', '%s')\n", psrc, pbuf);
|
|
return(pdst != pbuf);
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: CrackSources
|
|
//
|
|
// Synopsis: Parse the SOURCES= line in a sources file and adds those source
|
|
// files to the list of sources in the DIRREC struct.
|
|
//
|
|
// Arguments: [pdr] -- Directory record
|
|
// [pds] -- Supplemental directory information
|
|
// [i] -- Which platform we're parsing
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
CrackSources(DIRREC *pdr, DIRSUP *pds, int i)
|
|
{
|
|
LPSTR pszsubdir, plist;
|
|
LPSTR pszfile, pszpath;
|
|
FILEREC *pfr;
|
|
DIRREC *pdrParent;
|
|
DIRREC *pdrMachine;
|
|
DIRREC *pdrParentMachine;
|
|
DIRREC **ppdr;
|
|
LPSTR pszSources;
|
|
char path[DB_MAX_PATH_LENGTH];
|
|
|
|
pszSources = (i == 0)?
|
|
"SOURCES" : PossibleTargetMachines[i - 1]->SourceVariable;
|
|
|
|
pdrParent = pdrMachine = pdrParentMachine = NULL;
|
|
plist = pds->SourcesVariables[i];
|
|
while (SplitToken(path, ' ', &plist)) {
|
|
UCHAR SubDirMask, SrcFlags;
|
|
|
|
SubDirMask = 0;
|
|
ppdr = &pdr; // assume current directory
|
|
pszsubdir = path;
|
|
if (pszsubdir[0] == '.' && pszsubdir[1] == '\\') {
|
|
BuildError(
|
|
"%s: Ignoring current directory prefix in %s= entry: %s\n",
|
|
pdr->Name,
|
|
pszSources,
|
|
path);
|
|
pszsubdir += 2;
|
|
}
|
|
if (pszsubdir[0] == '.' &&
|
|
pszsubdir[1] == '.' &&
|
|
pszsubdir[2] == '\\') {
|
|
|
|
SubDirMask = TMIDIR_PARENT;
|
|
ppdr = &pdrParent; // assume parent directory
|
|
pszsubdir += 3;
|
|
}
|
|
pszpath = path;
|
|
pszfile = strchr(pszsubdir, '\\');
|
|
if (pszfile == NULL) {
|
|
pszfile = pszsubdir;
|
|
} else {
|
|
*pszfile = '\0';
|
|
if (i == 0 ||
|
|
_stricmp(
|
|
pszsubdir,
|
|
PossibleTargetMachines[i - 1]->SourceDirectory) != 0 ||
|
|
strchr(pszfile + 1, '\\') != NULL) {
|
|
|
|
*pszfile = '\\';
|
|
BuildError(
|
|
"%s: Ignoring invalid directory prefix in %s= entry: %s\n",
|
|
pdr->Name,
|
|
pszSources,
|
|
path);
|
|
|
|
//
|
|
|
|
pszpath = strrchr(path, '\\');
|
|
assert(pszpath != NULL);
|
|
pszpath++;
|
|
SubDirMask = 0;
|
|
ppdr = &pdr; // default to current direcory
|
|
}
|
|
else {
|
|
SubDirMask |= PossibleTargetMachines[i - 1]->SourceSubDirMask;
|
|
*pszfile++ = '\\';
|
|
if (SubDirMask & TMIDIR_PARENT) {
|
|
ppdr = &pdrParentMachine; // parent's machine sub dir
|
|
} else {
|
|
ppdr = &pdrMachine; // machine sub dir
|
|
}
|
|
}
|
|
}
|
|
NewDirectory:
|
|
if (*ppdr == NULL) {
|
|
pfr = FindSourceFileDB(pdr, pszpath, ppdr);
|
|
} else {
|
|
pfr = LookupFileDB(*ppdr, pszfile);
|
|
}
|
|
SrcFlags = SOURCEDB_SOURCES_LIST;
|
|
if ((pfr == NULL) && !fPassZero) {
|
|
if (fDebug) {
|
|
BuildError("%s: Missing source file: %s\n", pdr->Name, path);
|
|
}
|
|
if (*ppdr == NULL) {
|
|
if (fDebug || pszpath == path) {
|
|
BuildError(
|
|
"%s: Directory does not exist: %s\n",
|
|
pdr->Name,
|
|
path);
|
|
}
|
|
|
|
// Probably an error in the subordinate sources file.
|
|
// since old versions of build managed to get these entries
|
|
// into the objects lists, we have to do the same...
|
|
//
|
|
// If ..\ prefix exists, strip it off and try again.
|
|
// Else try again with the current directory.
|
|
|
|
if (SubDirMask & TMIDIR_PARENT) {
|
|
SubDirMask &= ~TMIDIR_PARENT; // strip off "..\\"
|
|
}
|
|
else {
|
|
SubDirMask = 0; // use current direcory
|
|
}
|
|
if (SubDirMask == 0) {
|
|
ppdr = &pdr; // current direcory
|
|
pszpath = pszfile;
|
|
}
|
|
else {
|
|
ppdr = &pdrMachine; // machine sub dir
|
|
pszpath = pszsubdir;
|
|
}
|
|
goto NewDirectory;
|
|
}
|
|
pfr = InsertFileDB(*ppdr, pszfile, 0, 0, FILEDB_FILE_MISSING);
|
|
if (pfr == NULL) {
|
|
BuildError(
|
|
"%s: Ignoring invalid %s= entry: %s\n",
|
|
pdr->Name,
|
|
pszSources,
|
|
path);
|
|
}
|
|
}
|
|
if (pfr != NULL) {
|
|
AssertFile(pfr);
|
|
if (SubDirMask == 0) {
|
|
pfr->FileFlags |= FILEDB_OBJECTS_LIST;
|
|
}
|
|
if (pfr->FileFlags & FILEDB_FILE_MISSING) {
|
|
SrcFlags |= SOURCEDB_FILE_MISSING;
|
|
}
|
|
InsertSourceDB(&pds->psrSourcesList[i], pfr, SubDirMask, SrcFlags);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: SaveUserTests
|
|
//
|
|
// Synopsis: Save the value of the UMTEST macro into the DIRREC struct.
|
|
//
|
|
// Arguments: [DirDB] -- Dir struct to save into
|
|
// [TextLine] -- String from UMTEST= line in sources file
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
SaveUserTests(
|
|
PDIRREC DirDB,
|
|
LPSTR TextLine)
|
|
{
|
|
UINT i;
|
|
BOOL fSave = FALSE;
|
|
char name[64];
|
|
char buf[512];
|
|
|
|
buf[0] = '\0';
|
|
if (DirDB->UserTests != NULL) {
|
|
strcpy(buf, DirDB->UserTests);
|
|
}
|
|
CopyString(TextLine, TextLine, TRUE);
|
|
while (SplitToken(name, '*', &TextLine)) {
|
|
for (i = 0; i < CountOptionalDirs; i++) {
|
|
if (!strcmp(name, OptionalDirs[i])) {
|
|
if (buf[0] != '\0') {
|
|
strcat(buf, "*");
|
|
DirDB->DirFlags |= DIRDB_FORCELINK; // multiple targets
|
|
}
|
|
strcat(buf, name);
|
|
fSave = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (fSave) {
|
|
MakeMacroString(&DirDB->UserTests, buf);
|
|
DirDB->DirFlags |= DIRDB_LINKNEEDED;
|
|
}
|
|
}
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ReadSourcesFile
|
|
//
|
|
// Synopsis: Parses the sources files (common and platform specific)
|
|
//
|
|
// Arguments: [DirDB] -- Directory containing sources file
|
|
// [pds] -- Supplementary info on directory
|
|
// [pDateTimeSources] -- Timestamp of Sources file
|
|
//
|
|
// Returns: TRUE if read successfully
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
ReadSourcesFile(DIRREC *DirDB, DIRSUP *pds, ULONG *pDateTimeSources)
|
|
{
|
|
FILE *InFileHandle;
|
|
LPSTR p, p1, TextLine;
|
|
LPSTR MacroName;
|
|
UINT i, iMacro;
|
|
int iTarget;
|
|
ULONG DateTime;
|
|
char path[DB_MAX_PATH_LENGTH];
|
|
BOOL fCleanNTTargetFile0 = FALSE;
|
|
BOOL fNOTARGETSeen = FALSE;
|
|
BOOL fNULLTARGETPATHSeen = FALSE;
|
|
|
|
memset(pds, 0, sizeof(*pds));
|
|
assert(DirDB->TargetPath == NULL);
|
|
assert(DirDB->TargetName == NULL);
|
|
assert(DirDB->TargetExt == NULL);
|
|
assert(DirDB->KernelTest == NULL);
|
|
assert(DirDB->UserAppls == NULL);
|
|
assert(DirDB->UserTests == NULL);
|
|
assert(DirDB->NTTargetFile0 == NULL);
|
|
assert(DirDB->Pch == NULL);
|
|
assert(DirDB->PchObj == NULL);
|
|
assert(cMacro == 0);
|
|
*pDateTimeSources = 0;
|
|
|
|
//
|
|
// Read the information in each of the target specific directories
|
|
// and simulate concatenation of all of the sources files.
|
|
//
|
|
// Possible sources files are read from DirDB->Name | target-source
|
|
// and DirDb->Name | ..\target-source.
|
|
//
|
|
// iTarget values, and the corresponding files processed are:
|
|
// -1 sources.
|
|
// 0 PossibleTargetMachines[0]\sources.
|
|
// 1 ..\PossibleTargetMachines[0]\sources.
|
|
// 2 PossibleTargetMachines[1]\sources.
|
|
// 3 ..\PossibleTargetMachines[1]\sources.
|
|
// 4 PossibleTargetMachines[2]\sources.
|
|
// 5 ..\PossibleTargetMachines[2]\sources.
|
|
|
|
SetObjDir(FALSE);
|
|
SaveMacro("_OBJ_DIR", pszObjDir);
|
|
for (iTarget = -1; iTarget < 2*MAX_TARGET_MACHINES; iTarget++) {
|
|
path[0] = '\0';
|
|
if (iTarget >= 0) {
|
|
if (iTarget & 1) {
|
|
strcat(path, "..\\");
|
|
}
|
|
strcat(path, PossibleTargetMachines[iTarget/2]->SourceDirectory);
|
|
strcat(path, "\\");
|
|
}
|
|
strcat(path, "sources.");
|
|
if (!SetupReadFile(DirDB->Name, path, "#", &InFileHandle)) {
|
|
if (iTarget == -1) {
|
|
return(FALSE);
|
|
}
|
|
continue; // skip non-existent subordinate sources files
|
|
}
|
|
if (DEBUG_1) {
|
|
BuildMsg(
|
|
" Scanning%s file %s\n",
|
|
iTarget >= 0? " subordinate" : "",
|
|
FormatPathName(DirDB->Name, path));
|
|
}
|
|
DirDB->DirFlags |= DIRDB_SOURCESREAD;
|
|
|
|
while ((TextLine = ReadLine(InFileHandle)) != NULL) {
|
|
LPSTR pValue;
|
|
|
|
pValue = SplitMacro(TextLine);
|
|
if (pValue == NULL) {
|
|
continue;
|
|
}
|
|
iMacro = 0;
|
|
|
|
//
|
|
// This sets pds->SourcesVariables[0] to the value of SOURCES= if
|
|
// the current line is SOURCES=...
|
|
//
|
|
if (SetMacroString(
|
|
"SOURCES",
|
|
TextLine,
|
|
pValue,
|
|
&pds->SourcesVariables[0])) {
|
|
|
|
iMacro = SOURCES_MAX;
|
|
DirDB->DirFlags |= DIRDB_SOURCES_SET;
|
|
}
|
|
else {
|
|
for (i = 0; i < MAX_TARGET_MACHINES; i++) {
|
|
//
|
|
// This sets pds->SourcesVariables[0] to the value of
|
|
// PLAT_SOURCES= if the current line is PLAT_SOURCES=...
|
|
//
|
|
if (SetMacroString(
|
|
PossibleTargetMachines[i]->SourceVariable,
|
|
TextLine,
|
|
pValue,
|
|
&pds->SourcesVariables[i + 1])) {
|
|
|
|
iMacro = SOURCES_MAX;
|
|
DirDB->DirFlags |= DIRDB_SOURCES_SET;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
while ((MacroName = RelevantSourcesMacros[iMacro]) != NULL) {
|
|
if (_stricmp(TextLine, MacroName) == 0) {
|
|
break;
|
|
}
|
|
iMacro++;
|
|
}
|
|
if (MacroName != NULL) { // if macro name found in list
|
|
switch (iMacro) {
|
|
LPSTR *ppszPath;
|
|
LPSTR *ppszFile;
|
|
|
|
case SOURCES_TARGETNAME:
|
|
MakeMacroString(&DirDB->TargetName, pValue);
|
|
break;
|
|
|
|
case SOURCES_TARGETPATH:
|
|
// HACK
|
|
if (strcmp(pValue, "obj") == 0) {
|
|
pValue = pszObjDir;
|
|
}
|
|
MakeMacroString(&DirDB->TargetPath, pValue);
|
|
if (DirDB->TargetPath != NULL) {
|
|
CreateBuildDirectory(DirDB->TargetPath);
|
|
for (i = 0; i < CountTargetMachines; i++) {
|
|
p1 = TargetMachines[i]->ObjectDirectory[iObjectDir];
|
|
assert(strncmp(pszObjDirSlash, p1, strlen(pszObjDirSlash)) == 0);
|
|
p1 += strlen(pszObjDirSlash);
|
|
sprintf(path, "%s\\%s", DirDB->TargetPath, p1);
|
|
CreateBuildDirectory(path);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SOURCES_TARGETTYPE:
|
|
if (!_stricmp(pValue, "PROGRAM")) {
|
|
DirDB->TargetExt = ".exe";
|
|
DirDB->DirFlags |= DIRDB_LINKNEEDED;
|
|
}
|
|
else
|
|
if (!_stricmp(pValue, "DRIVER")) {
|
|
DirDB->TargetExt = ".sys";
|
|
DirDB->DirFlags |= DIRDB_LINKNEEDED;
|
|
}
|
|
else
|
|
if (!_stricmp(pValue, "GDI_DRIVER")) {
|
|
DirDB->TargetExt = ".dll";
|
|
DirDB->DirFlags |= DIRDB_LINKNEEDED;
|
|
}
|
|
else
|
|
if (!_stricmp(pValue, "MINIPORT")) {
|
|
DirDB->TargetExt = ".sys";
|
|
DirDB->DirFlags |= DIRDB_LINKNEEDED;
|
|
}
|
|
else
|
|
if (!_stricmp(pValue, "EXPORT_DRIVER")) {
|
|
DirDB->TargetExt = ".sys";
|
|
DirDB->DirFlags |= DIRDB_LINKNEEDED;
|
|
DirDB->DirFlags |= DIRDB_DLLTARGET;
|
|
}
|
|
else
|
|
if (!_stricmp(pValue, "DYNLINK")) {
|
|
DirDB->TargetExt = ".dll";
|
|
DirDB->DirFlags |= DIRDB_LINKNEEDED;
|
|
DirDB->DirFlags |= DIRDB_DLLTARGET;
|
|
}
|
|
else
|
|
if (!_stricmp(pValue, "HAL")) {
|
|
DirDB->TargetExt = ".dll";
|
|
DirDB->DirFlags |= DIRDB_LINKNEEDED;
|
|
DirDB->DirFlags |= DIRDB_DLLTARGET;
|
|
}
|
|
else
|
|
if (!_stricmp(pValue, "LIBRARY")) {
|
|
DirDB->TargetExt = ".lib";
|
|
DirDB->DirFlags &= ~DIRDB_LINKNEEDED;
|
|
}
|
|
else
|
|
if (!_stricmp(pValue, "PROGLIB")) {
|
|
DirDB->TargetExt = ".exe";
|
|
DirDB->DirFlags |= DIRDB_LINKNEEDED;
|
|
}
|
|
else
|
|
if (!_stricmp(pValue, "UMAPPL_NOLIB")) {
|
|
DirDB->DirFlags &= ~DIRDB_LINKNEEDED;
|
|
}
|
|
else
|
|
if (!_stricmp(pValue, "NOTARGET")) {
|
|
//
|
|
// Used to indicate no target for a directory,
|
|
// e.g. if only pass0 files are generated
|
|
fNOTARGETSeen = TRUE;
|
|
DirDB->DirFlags &= ~DIRDB_LINKNEEDED;
|
|
if (!fQuicky) {
|
|
DirDB->DirFlags |= DIRDB_COMPILENEEDED;
|
|
}
|
|
}
|
|
else {
|
|
BuildError(
|
|
"Unsupported TARGETTYPE value - %s\n",
|
|
pValue);
|
|
}
|
|
break;
|
|
|
|
case SOURCES_TARGETEXT:
|
|
if (!_stricmp(pValue, "dll")) {
|
|
DirDB->TargetExt = ".dll";
|
|
}
|
|
else
|
|
if (!_stricmp(pValue, "fon")) {
|
|
DirDB->TargetExt = ".fon";
|
|
}
|
|
else
|
|
if (!_stricmp(pValue, "cpl")) {
|
|
DirDB->TargetExt = ".cpl";
|
|
}
|
|
else
|
|
if (!_stricmp(pValue, "drv")) {
|
|
DirDB->TargetExt = ".drv";
|
|
}
|
|
else
|
|
if (!_stricmp(pValue, "tsp")) {
|
|
DirDB->TargetExt = ".tsp";
|
|
}
|
|
else
|
|
if (!_stricmp(pValue, "pkg")) {
|
|
DirDB->TargetExt = ".pkg";
|
|
}
|
|
else
|
|
if (!_stricmp(pValue, "awx")) {
|
|
DirDB->TargetExt = ".awx";
|
|
}
|
|
else
|
|
if (!_stricmp(pValue, "ocx")) {
|
|
DirDB->TargetExt = ".ocx";
|
|
}
|
|
else
|
|
if (!_stricmp(pValue, "ime")) {
|
|
DirDB->TargetExt = ".ime";
|
|
}
|
|
else
|
|
if (!_stricmp(pValue, "tsp")) {
|
|
DirDB->TargetExt = ".tsp";
|
|
}
|
|
else {
|
|
BuildError(
|
|
"Unsupported TARGETEXT value - %s\n",
|
|
pValue);
|
|
}
|
|
break;
|
|
|
|
case SOURCES_INCLUDES:
|
|
MakeMacroString(&pds->LocalIncludePath, pValue);
|
|
if (DEBUG_1) {
|
|
BuildMsg(
|
|
" Found local INCLUDES=%s\n",
|
|
pds->LocalIncludePath);
|
|
}
|
|
break;
|
|
|
|
case SOURCES_MFC_INCLUDES:
|
|
// MFC_INCLUDES/SDK_INC/CRT_INC/OAK_INC really can't be changed
|
|
// in the sources file (yet) since we've already processed the
|
|
// system includes. Lay the groundwork for now.
|
|
MakeMacroString((char **)&pszIncMfc, pValue);
|
|
break;
|
|
|
|
case SOURCES_SDK_INC_PATH:
|
|
MakeMacroString((char **)&pszIncSdk, pValue);
|
|
break;
|
|
|
|
case SOURCES_CRT_INC_PATH:
|
|
MakeMacroString((char **)&pszIncCrt, pValue);
|
|
break;
|
|
|
|
case SOURCES_OAK_INC_PATH:
|
|
MakeMacroString((char **)&pszIncOak, pValue);
|
|
break;
|
|
|
|
case SOURCES_PRECOMPILED_PCH:
|
|
MakeMacroString(&DirDB->Pch, pValue);
|
|
break;
|
|
|
|
case SOURCES_PRECOMPILED_OBJ:
|
|
MakeMacroString(&DirDB->PchObj, pValue);
|
|
break;
|
|
|
|
case SOURCES_PRECOMPILED_INCLUDE:
|
|
case SOURCES_PRECOMPILED_TARGET:
|
|
if (iMacro == SOURCES_PRECOMPILED_INCLUDE) {
|
|
ppszPath = &pds->PchIncludeDir;
|
|
ppszFile = &pds->PchInclude;
|
|
} else {
|
|
ppszPath = &pds->PchTargetDir;
|
|
ppszFile = &pds->PchTarget;
|
|
}
|
|
|
|
MakeMacroString(ppszPath, ""); // free old string
|
|
if (!MakeMacroString(ppszFile, pValue)) {
|
|
break;
|
|
}
|
|
p = *ppszFile + strlen(*ppszFile);
|
|
while (p > *ppszFile && *--p != '\\')
|
|
;
|
|
|
|
if (p > *ppszFile) {
|
|
*p = '\0';
|
|
MakeMacroString(ppszPath, *ppszFile);
|
|
MakeMacroString(ppszFile, p + 1);
|
|
}
|
|
|
|
if (DEBUG_1) {
|
|
BuildMsg(
|
|
"Precompiled header%s is %s in directory %s\n",
|
|
iMacro == SOURCES_PRECOMPILED_INCLUDE?
|
|
"" : " target",
|
|
*ppszFile,
|
|
*ppszPath != NULL?
|
|
*ppszPath : "'.'");
|
|
}
|
|
|
|
if (iMacro == SOURCES_PRECOMPILED_INCLUDE ||
|
|
pds->PchTargetDir == NULL) {
|
|
|
|
break;
|
|
}
|
|
|
|
EnsureDirectoriesExist(pds->PchTargetDir);
|
|
break;
|
|
|
|
case SOURCES_PASS0_HEADERDIR:
|
|
MakeMacroString(&pds->PassZeroHdrDir, pValue);
|
|
EnsureDirectoriesExist(pds->PassZeroHdrDir);
|
|
if (DEBUG_1)
|
|
{
|
|
BuildMsg("Pass Zero Header Directory is '%s'\n",
|
|
pds->PassZeroHdrDir);
|
|
}
|
|
break;
|
|
|
|
case SOURCES_PASS0_SOURCEDIR:
|
|
case SOURCES_PASS0_CLIENTDIR:
|
|
// SOURCES_PASS0_SOURCEDIR and SOURCES_PASS0_CLIENTDIR
|
|
// are mutually exclusive - enforced by makefile.def
|
|
MakeMacroString(&pds->PassZeroSrcDir1, pValue);
|
|
EnsureDirectoriesExist(pds->PassZeroSrcDir1);
|
|
if (DEBUG_1)
|
|
{
|
|
BuildMsg("Pass Zero Source/Client Directory is '%s'\n",
|
|
pds->PassZeroSrcDir1);
|
|
}
|
|
break;
|
|
|
|
case SOURCES_MIDL_UUIDDIR:
|
|
case SOURCES_PASS0_SERVERDIR:
|
|
// SOURCES_MIDL_UUIDDIR and SOURCES_PASS0_SERVERDIR
|
|
// are mutually exclusive - enforced by makefile.def
|
|
MakeMacroString(&pds->PassZeroSrcDir2, pValue);
|
|
EnsureDirectoriesExist(pds->PassZeroSrcDir2);
|
|
if (DEBUG_1)
|
|
{
|
|
BuildMsg("Midl UUID/Server Source Directory is '%s'\n",
|
|
pds->PassZeroSrcDir2);
|
|
}
|
|
break;
|
|
|
|
case SOURCES_NTTEST:
|
|
for (i = 0; i < CountOptionalDirs; i++) {
|
|
if (!_stricmp(pValue, OptionalDirs[i])) {
|
|
if (MakeMacroString(&DirDB->KernelTest, pValue)) {
|
|
DirDB->DirFlags |= DIRDB_LINKNEEDED;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SOURCES_UMTYPE:
|
|
MakeMacroString(&pds->TestType, pValue);
|
|
if (DEBUG_1) {
|
|
BuildMsg(
|
|
" Found UMTYPE=%s\n",
|
|
pds->TestType);
|
|
}
|
|
break;
|
|
|
|
case SOURCES_UMTEST:
|
|
case SOURCES_OPTIONAL_UMTEST:
|
|
SaveUserTests(DirDB, pValue);
|
|
break;
|
|
|
|
case SOURCES_UMAPPL:
|
|
if (MakeMacroString(&DirDB->UserAppls, pValue)) {
|
|
DirDB->DirFlags |= DIRDB_LINKNEEDED;
|
|
}
|
|
break;
|
|
|
|
case SOURCES_UMAPPLEXT:
|
|
if (!_stricmp(pValue, ".exe")) {
|
|
DirDB->TargetExt = ".exe";
|
|
}
|
|
else
|
|
if (!_stricmp(pValue, ".com")) {
|
|
DirDB->TargetExt = ".com";
|
|
}
|
|
else
|
|
if (!_stricmp(pValue, ".scr")) {
|
|
DirDB->TargetExt = ".scr";
|
|
}
|
|
else {
|
|
BuildError(
|
|
"Unsupported UMAPPLEXT value - %s\n",
|
|
pValue);
|
|
}
|
|
break;
|
|
|
|
case SOURCES_IDLTYPE:
|
|
if (!_stricmp(pValue, "ole")) {
|
|
pds->IdlType = 0;
|
|
}
|
|
else
|
|
if (!_stricmp(pValue, "rpc")) {
|
|
pds->IdlType = 1;
|
|
}
|
|
else {
|
|
BuildError(
|
|
"Unsupported IDL_TYPE value - %s\n",
|
|
pValue);
|
|
}
|
|
break;
|
|
|
|
case SOURCES_SOURCES_OPTIONS:
|
|
fCleanNTTargetFile0 = fClean && strstr(pValue, "-c0");
|
|
break;
|
|
|
|
case SOURCES_NTTARGETFILE0:
|
|
DirDB->DirFlags |= DIRDB_TARGETFILE0;
|
|
if (fCleanNTTargetFile0) {
|
|
MakeMacroString(&DirDB->NTTargetFile0, pValue);
|
|
}
|
|
break;
|
|
|
|
case SOURCES_NTTARGETFILES:
|
|
DirDB->DirFlags |= DIRDB_TARGETFILES;
|
|
break;
|
|
|
|
case SOURCES_CAIRO_PRODUCT:
|
|
DirDB->DirFlags |= DIRDB_CAIRO_INCLUDES;
|
|
break;
|
|
|
|
case SOURCES_CHICAGO_PRODUCT:
|
|
DirDB->DirFlags |= DIRDB_CHICAGO_INCLUDES;
|
|
break;
|
|
|
|
case SOURCES_CONDITIONAL_INCLUDES:
|
|
MakeMacroString(&pds->ConditionalIncludes, pValue);
|
|
break;
|
|
|
|
case SOURCES_SYNCHRONIZE_BLOCK:
|
|
DirDB->DirFlags |= DIRDB_SYNCHRONIZE_BLOCK;
|
|
break;
|
|
|
|
case SOURCES_SYNCHRONIZE_DRAIN:
|
|
DirDB->DirFlags |= DIRDB_SYNCHRONIZE_DRAIN;
|
|
break;
|
|
|
|
case SOURCES_CHECKED_ALT_DIR:
|
|
DirDB->DirFlags |= DIRDB_CHECKED_ALT_DIR;
|
|
if (DEBUG_1) {
|
|
BuildMsg("Found CHECKED_ALT_DIR\n");
|
|
}
|
|
SetObjDir(TRUE);
|
|
if (fCheckedBuild) {
|
|
SaveMacro("_OBJ_DIR", pszObjDir);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
SaveMacro(TextLine, pValue);
|
|
}
|
|
DateTime = CloseReadFile(NULL);
|
|
if (*pDateTimeSources < DateTime) {
|
|
*pDateTimeSources = DateTime; // keep newest timestamp
|
|
}
|
|
}
|
|
|
|
if (!fNOTARGETSeen && (DirDB->TargetPath == NULL)) {
|
|
BuildError(
|
|
"Unknown TARGETPATH value\n",
|
|
NULL);
|
|
}
|
|
|
|
FreeMacros();
|
|
|
|
if (fCairoProduct) {
|
|
DirDB->DirFlags |= DIRDB_CAIRO_INCLUDES;
|
|
}
|
|
else
|
|
if (fChicagoProduct) {
|
|
DirDB->DirFlags |= DIRDB_CHICAGO_INCLUDES;
|
|
}
|
|
|
|
//
|
|
// Directory has pass0 files in it (.idl, .mc, .asn, etc), check to make
|
|
// sure they specified where the generated files should go. Default to the
|
|
// obj subdirectories if they didn't. These always need to be non-null.
|
|
//
|
|
if (!pds->PassZeroHdrDir) {
|
|
MakeString(&pds->PassZeroHdrDir, ".", TRUE, MT_DIRSTRING);
|
|
}
|
|
|
|
if (!pds->PassZeroSrcDir1) {
|
|
MakeString(&pds->PassZeroSrcDir1, ".", TRUE, MT_DIRSTRING);
|
|
}
|
|
|
|
if (!pds->PassZeroSrcDir2)
|
|
MakeString(&pds->PassZeroSrcDir2, pds->PassZeroSrcDir1, TRUE, MT_DIRSTRING);
|
|
|
|
if (DirDB->UserTests != NULL) {
|
|
_strlwr(DirDB->UserTests);
|
|
}
|
|
if (DirDB->UserAppls != NULL) {
|
|
if (DirDB->UserTests != NULL || strchr(DirDB->UserAppls, '*') != NULL) {
|
|
DirDB->DirFlags |= DIRDB_FORCELINK; // multiple targets
|
|
}
|
|
}
|
|
|
|
PostProcessSources(DirDB, pds);
|
|
|
|
if (DEBUG_1) {
|
|
PrintDirDB(DirDB, 1|2);
|
|
PrintDirSupData(pds);
|
|
PrintDirDB(DirDB, 4);
|
|
}
|
|
|
|
pds->DateTimeSources = *pDateTimeSources;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: PostProcessSources
|
|
//
|
|
// Synopsis: Scan the files in the given directory and add files to the
|
|
// directory's list of source files (SOURCEREC), including PCH
|
|
// files, UMTEST files, etc.
|
|
//
|
|
// Arguments: [pdr] -- Directory to process
|
|
// [pds] -- Directory supplemental information
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void
|
|
PostProcessSources(DIRREC *pdr, DIRSUP *pds)
|
|
{
|
|
PFILEREC FileDB, *FileDBNext;
|
|
char path[DB_MAX_PATH_LENGTH];
|
|
LPSTR p, p1;
|
|
UINT i;
|
|
|
|
for (i = 0; i < MAX_TARGET_MACHINES + 1; i++) {
|
|
if (pds->SourcesVariables[i] != NULL) {
|
|
CrackSources(pdr, pds, i);
|
|
}
|
|
}
|
|
|
|
FileDBNext = &pdr->Files;
|
|
while (FileDB = *FileDBNext) {
|
|
|
|
if (pds->PchInclude && strcmp(FileDB->Name, pds->PchInclude) == 0) {
|
|
InsertSourceDB(&pds->psrSourcesList[0], FileDB, 0, SOURCEDB_PCH);
|
|
if (DEBUG_1) {
|
|
BuildMsg("Adding PCH file to Sources List: %s.\n", FileDB->Name);
|
|
}
|
|
}
|
|
|
|
if ((FileDB->FileFlags & (FILEDB_SOURCE | FILEDB_OBJECTS_LIST)) ==
|
|
FILEDB_SOURCE) {
|
|
|
|
p = FileDB->Name;
|
|
p1 = path;
|
|
while (*p != '\0' && *p != '.') {
|
|
*p1++ = *p++;
|
|
}
|
|
*p1 = '\0';
|
|
_strlwr(path);
|
|
if (pdr->KernelTest != NULL &&
|
|
!strcmp(path, pdr->KernelTest)) {
|
|
|
|
FileDB->FileFlags |= FILEDB_OBJECTS_LIST;
|
|
}
|
|
else
|
|
if (pdr->UserAppls != NULL &&
|
|
(p = strstr(pdr->UserAppls, path)) &&
|
|
(p == pdr->UserAppls || p[-1] == '*' || p[-1] == ' ')) {
|
|
FileDB->FileFlags |= FILEDB_OBJECTS_LIST;
|
|
}
|
|
else
|
|
if (pdr->UserTests != NULL &&
|
|
(p = strstr(pdr->UserTests, path)) &&
|
|
(p == pdr->UserTests || p[-1] == '*' || p[-1] == ' ')) {
|
|
|
|
FileDB->FileFlags |= FILEDB_OBJECTS_LIST;
|
|
}
|
|
if (FileDB->FileFlags & FILEDB_OBJECTS_LIST) {
|
|
InsertSourceDB(&pds->psrSourcesList[0], FileDB, 0, 0);
|
|
}
|
|
}
|
|
FileDBNext = &FileDB->Next;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: ReadDirsFile
|
|
//
|
|
// Synopsis: Parse the DIRS file
|
|
//
|
|
// Arguments: [DirDB] -- Directory to look in
|
|
//
|
|
// Returns: TRUE if parsed
|
|
//
|
|
// Notes: The existence of a file named 'mydirs' will override the
|
|
// normal 'dirs' file.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
ReadDirsFile(
|
|
PDIRREC DirDB
|
|
)
|
|
{
|
|
FILE *InFileHandle;
|
|
LPSTR TextLine, pValue;
|
|
LPSTR apszDirs[] = { "mydirs.", "dirs.", NULL };
|
|
|
|
for (ppCurrentDirsFileName = apszDirs;
|
|
*ppCurrentDirsFileName != NULL;
|
|
ppCurrentDirsFileName++) {
|
|
if (SetupReadFile(DirDB->Name, *ppCurrentDirsFileName, "#", &InFileHandle)) {
|
|
break;
|
|
}
|
|
}
|
|
if (*ppCurrentDirsFileName == NULL) {
|
|
return(FALSE);
|
|
}
|
|
|
|
if (fFirstScan && (ppCurrentDirsFileName == apszDirs))
|
|
{
|
|
BuildMsg("Using .\\%s instead of DIRS...\n",
|
|
FormatPathName(DirDB->Name, *ppCurrentDirsFileName));
|
|
}
|
|
|
|
if (DEBUG_1) {
|
|
BuildMsg(
|
|
" Scanning file %s\n",
|
|
FormatPathName(DirDB->Name, *ppCurrentDirsFileName));
|
|
}
|
|
|
|
assert(cMacro == 0);
|
|
while ((TextLine = ReadLine(InFileHandle)) != NULL) {
|
|
if ((pValue = SplitMacro(TextLine)) != NULL) {
|
|
SaveMacro(TextLine, pValue);
|
|
}
|
|
}
|
|
CloseReadFile(NULL);
|
|
if ((pValue = FindMacro("DIRS")) != NULL) {
|
|
MarkDirNames(DirDB, pValue, TRUE);
|
|
}
|
|
if ((pValue = FindMacro("OPTIONAL_DIRS")) != NULL) {
|
|
MarkDirNames(DirDB, pValue, FALSE);
|
|
}
|
|
if ((FindMacro("SYNCHRONIZE_DRAIN")) != NULL) {
|
|
DirDB->DirFlags |= DIRDB_SYNCHRONIZE_DRAIN;
|
|
}
|
|
FreeMacros();
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
//
|
|
// Debugging and Utility Functions
|
|
//
|
|
|
|
VOID
|
|
PrintDirSupData(DIRSUP *pds)
|
|
{
|
|
int i;
|
|
|
|
if (pds->LocalIncludePath != NULL) {
|
|
BuildMsgRaw(" LocalIncludePath: %s\n", pds->LocalIncludePath);
|
|
}
|
|
if (pds->TestType != NULL) {
|
|
BuildMsgRaw(" TestType: %s\n", pds->TestType);
|
|
}
|
|
if (pds->PchIncludeDir != NULL) {
|
|
BuildMsgRaw(" PchIncludeDir: %s\n", pds->PchIncludeDir);
|
|
}
|
|
if (pds->PchInclude != NULL) {
|
|
BuildMsgRaw(" PchInclude: %s\n", pds->PchInclude);
|
|
}
|
|
if (pds->PchTargetDir != NULL) {
|
|
BuildMsgRaw(" PchTargetDir: %s\n", pds->PchTargetDir);
|
|
}
|
|
if (pds->PchTarget != NULL) {
|
|
BuildMsgRaw(" PchTarget: %s\n", pds->PchTarget);
|
|
}
|
|
if (pds->ConditionalIncludes != NULL) {
|
|
BuildMsgRaw(" ConditionalIncludes: %s\n", pds->ConditionalIncludes);
|
|
}
|
|
for (i = 0; i < MAX_TARGET_MACHINES + 1; i++) {
|
|
if (pds->SourcesVariables[i] != NULL) {
|
|
BuildMsgRaw(
|
|
" SourcesVariables[%d]: %s\n",
|
|
i,
|
|
pds->SourcesVariables[i]);
|
|
}
|
|
if (pds->psrSourcesList[i] != NULL) {
|
|
BuildMsgRaw(" SourcesList[%d]:\n", i);
|
|
PrintSourceDBList(pds->psrSourcesList[i], i - 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
FreeDirSupData(DIRSUP *pds)
|
|
{
|
|
int i;
|
|
|
|
if (pds->LocalIncludePath != NULL) {
|
|
FreeMem(&pds->LocalIncludePath, MT_DIRSTRING);
|
|
}
|
|
if (pds->TestType != NULL) {
|
|
FreeMem(&pds->TestType, MT_DIRSTRING);
|
|
}
|
|
if (pds->PchInclude != NULL) {
|
|
FreeMem(&pds->PchInclude, MT_DIRSTRING);
|
|
}
|
|
if (pds->PchIncludeDir != NULL) {
|
|
FreeMem(&pds->PchIncludeDir, MT_DIRSTRING);
|
|
}
|
|
if (pds->PchTargetDir != NULL) {
|
|
FreeMem(&pds->PchTargetDir, MT_DIRSTRING);
|
|
}
|
|
if (pds->PchTarget != NULL) {
|
|
FreeMem(&pds->PchTarget, MT_DIRSTRING);
|
|
}
|
|
if (pds->ConditionalIncludes != NULL) {
|
|
FreeMem(&pds->ConditionalIncludes, MT_DIRSTRING);
|
|
}
|
|
if (pds->PassZeroHdrDir != NULL) {
|
|
FreeMem(&pds->PassZeroHdrDir, MT_DIRSTRING);
|
|
}
|
|
if (pds->PassZeroSrcDir1 != NULL) {
|
|
FreeMem(&pds->PassZeroSrcDir1, MT_DIRSTRING);
|
|
}
|
|
if (pds->PassZeroSrcDir2 != NULL) {
|
|
FreeMem(&pds->PassZeroSrcDir2, MT_DIRSTRING);
|
|
}
|
|
for (i = 0; i < MAX_TARGET_MACHINES + 1; i++) {
|
|
if (pds->SourcesVariables[i] != NULL) {
|
|
FreeMem(&pds->SourcesVariables[i], MT_DIRSTRING);
|
|
}
|
|
while (pds->psrSourcesList[i] != NULL) {
|
|
FreeSourceDB(&pds->psrSourcesList[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
FreeDirData(DIRREC *pdr)
|
|
{
|
|
if (pdr->TargetPath != NULL) {
|
|
FreeMem(&pdr->TargetPath, MT_DIRSTRING);
|
|
}
|
|
if (pdr->TargetName != NULL) {
|
|
FreeMem(&pdr->TargetName, MT_DIRSTRING);
|
|
}
|
|
if (pdr->KernelTest != NULL) {
|
|
FreeMem(&pdr->KernelTest, MT_DIRSTRING);
|
|
}
|
|
if (pdr->UserAppls != NULL) {
|
|
FreeMem(&pdr->UserAppls, MT_DIRSTRING);
|
|
}
|
|
if (pdr->UserTests != NULL) {
|
|
FreeMem(&pdr->UserTests, MT_DIRSTRING);
|
|
}
|
|
if (pdr->NTTargetFile0 != NULL) {
|
|
FreeMem(&pdr->NTTargetFile0, MT_DIRSTRING);
|
|
}
|
|
if (pdr->Pch != NULL) {
|
|
FreeMem(&pdr->Pch, MT_DIRSTRING);
|
|
}
|
|
if (pdr->PchObj != NULL) {
|
|
FreeMem(&pdr->PchObj, MT_DIRSTRING);
|
|
}
|
|
if (pdr->pds != NULL) {
|
|
FreeDirSupData(pdr->pds);
|
|
FreeMem(&pdr->pds, MT_DIRSUP);
|
|
pdr->pds = NULL;
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: MarkDirNames
|
|
//
|
|
// Synopsis: Parses a DIRS= or OPTIONAL_DIRS line and marks the directories
|
|
// appropriately.
|
|
//
|
|
// Arguments: [DirDB] -- Directory containing DIRS file
|
|
// [TextLine] -- DIRS= or OPTIONAL_DIRS= line
|
|
// [Required] -- Indicates if directories are optional or not.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
MarkDirNames(PDIRREC DirDB, LPSTR TextLine, BOOL Required)
|
|
{
|
|
UINT i;
|
|
LPSTR p;
|
|
PFILEREC FileDB, *FileDBNext;
|
|
char dirbuf[64];
|
|
|
|
AssertPathString(TextLine);
|
|
while (SplitToken(dirbuf, '*', &TextLine)) {
|
|
for (p = dirbuf; *p != '\0'; p++) {
|
|
if (!iscsym(*p) && *p != '.') {
|
|
BuildError(
|
|
"%s: ignoring bad subdirectory: %s\n",
|
|
DirDB->Name,
|
|
dirbuf);
|
|
p = NULL;
|
|
break;
|
|
}
|
|
}
|
|
if (p != NULL) {
|
|
if (!Required) {
|
|
for (i = 0; i < CountOptionalDirs; i++) {
|
|
if (!strcmp(dirbuf, OptionalDirs[i])) {
|
|
OptionalDirsUsed[i] = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (i >= CountOptionalDirs) {
|
|
p = NULL;
|
|
}
|
|
}
|
|
else {
|
|
for (i = 0; i < CountExcludeDirs; i++) {
|
|
if (!strcmp(dirbuf, ExcludeDirs[i])) {
|
|
ExcludeDirsUsed[i] = TRUE;
|
|
p = NULL;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (p != NULL) {
|
|
if (fQuicky || fSemiQuicky) {
|
|
FileDB = InsertFileDB(
|
|
DirDB,
|
|
dirbuf,
|
|
0,
|
|
FILE_ATTRIBUTE_DIRECTORY,
|
|
0);
|
|
if (FileDB != NULL) {
|
|
FileDB->SubDirIndex = ++DirDB->CountSubDirs;
|
|
}
|
|
}
|
|
else {
|
|
FileDBNext = &DirDB->Files;
|
|
while (FileDB = *FileDBNext) {
|
|
if (FileDB->FileFlags & FILEDB_DIR) {
|
|
if (!strcmp(dirbuf, FileDB->Name)) {
|
|
FileDB->SubDirIndex = ++DirDB->CountSubDirs;
|
|
break;
|
|
}
|
|
}
|
|
FileDBNext = &FileDB->Next;
|
|
}
|
|
if (FileDB == NULL) {
|
|
BuildError(
|
|
"%s found in %s, is not a subdirectory of %s\n",
|
|
dirbuf,
|
|
FormatPathName(DirDB->Name, *ppCurrentDirsFileName),
|
|
DirDB->Name);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
StartElapsedTime(VOID)
|
|
{
|
|
if (fPrintElapsed && StartTime == 0) {
|
|
StartTime = GetTickCount();
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
PrintElapsedTime(VOID)
|
|
{
|
|
DWORD ElapsedTime;
|
|
DWORD ElapsedHours;
|
|
DWORD ElapsedMinutes;
|
|
DWORD ElapsedSeconds;
|
|
DWORD ElapsedMilliseconds;
|
|
|
|
if (fPrintElapsed) {
|
|
ElapsedTime = GetTickCount() - StartTime;
|
|
ElapsedHours = ElapsedTime/(1000 * 60 * 60);
|
|
ElapsedTime = ElapsedTime % (1000 * 60 * 60);
|
|
ElapsedMinutes = ElapsedTime/(1000 * 60);
|
|
ElapsedTime = ElapsedTime % (1000 * 60);
|
|
ElapsedSeconds = ElapsedTime/1000;
|
|
ElapsedMilliseconds = ElapsedTime % 1000;
|
|
BuildMsg(
|
|
"Elapsed time [%d:%02d:%02d.%03d]\n",
|
|
ElapsedHours,
|
|
ElapsedMinutes,
|
|
ElapsedSeconds,
|
|
ElapsedMilliseconds);
|
|
LogMsg(
|
|
"Elapsed time [%d:%02d:%02d.%03d]%s\n",
|
|
ElapsedHours,
|
|
ElapsedMinutes,
|
|
ElapsedSeconds,
|
|
ElapsedMilliseconds,
|
|
szAsterisks);
|
|
}
|
|
}
|