MWCC/command_line/CmdLine/Src/CLDependencies.c

406 lines
12 KiB
C

#include "cmdline.h"
extern char STSbuf[256];
static Path *specialAccessPath;
SInt16 *CLT_filesp;
CPrepFileInfoStack *CLT_filestack;
// forward decl
static Boolean FindFileInPaths(Paths *paths, const char *filename, Path **thepath, OSSpec *spec);
static void SetSpecialAccessPathFromIncludeStackTOS();
Boolean Incls_Initialize(Incls *incls, Target *targ) {
specialAccessPath = NULL;
incls->targ = targ;
incls->maxincls = 0;
incls->numincls = 0;
incls->bufpos = 0;
incls->buflen = 0;
incls->buffer = NULL;
incls->files = NULL;
incls->allPaths = xmalloc(NULL, sizeof(Paths));
Paths_Initialize(incls->allPaths);
return 1;
}
void Incls_Terminate(Incls *incls) {
if (incls->buffer)
xfree(incls->buffer);
if (incls->files)
xfree(incls->files);
Paths_Terminate(incls->allPaths);
xfree(incls->allPaths);
}
static Boolean IsSysIncl(Incls *incls, SInt32 idx) {
InclFile *i = &incls->files[idx];
return i->syspath;
}
static void MakeInclFileSpec(Incls *incls, SInt32 idx, OSSpec *spec) {
InclFile *f = &incls->files[idx];
OS_MakeSpecWithPath(
f->globalpath->spec,
&incls->buffer[f->filenameoffs],
0,
spec);
}
static Boolean QuickFindFileInIncls(Incls *incls, Boolean fullsearch, const char *filename, OSSpec *spec, SInt32 *index, InclFile **f) {
int idx;
for (idx = 0; idx < incls->numincls; idx++) {
*f = &incls->files[idx];
if (OS_EqualPath(&incls->buffer[(*f)->filenameoffs], filename)) {
if (fullsearch || (*f)->syspath) {
MakeInclFileSpec(incls, idx, spec);
*index = idx;
return 1;
}
}
}
return 0;
}
static Boolean SameIncl(Incls *incls, SInt32 a, SInt32 b) {
InclFile *ia;
InclFile *ib;
if (a == b)
return 1;
ia = &incls->files[a];
ib = &incls->files[b];
return ia->globalpath == ib->globalpath && OS_EqualPath(&incls->buffer[ia->filenameoffs], &incls->buffer[ib->filenameoffs]);
}
static Path *FindOrAddGlobalInclPath(Paths *paths, OSPathSpec *spec) {
Path *path = Paths_FindPathSpec(paths, spec);
if (!path) {
path = Path_New(spec);
Paths_AddPath(paths, path);
}
return path;
}
static Boolean _FindFileInPath(Path *path, const char *filename, Path **thepath, OSSpec *spec) {
if (!OS_MakeSpecWithPath(path->spec, filename, 0, spec) && OS_IsFile(spec)) {
*thepath = path;
return 1;
}
if (path->recursive && FindFileInPaths(path->recursive, filename, thepath, spec))
return 1;
return 0;
}
static Boolean FindFileInPaths(Paths *paths, const char *filename, Path **thepath, OSSpec *spec) {
UInt16 idx;
Path *path;
for (idx = 0; idx < Paths_Count(paths); idx++) {
path = Paths_GetPath(paths, idx);
OS_ASSERT(175, path);
if (_FindFileInPath(path, filename, thepath, spec))
return 1;
}
return 0;
}
static void AddFileToIncls(Incls *incls, char *infilename, Boolean syspath, Path *accesspath, Path *globalpath, Path *specialpath, SInt32 *index) {
InclFile *f;
int fnlen;
char *filename;
OSSpec spec;
if (!accesspath && !globalpath)
filename = OS_GetFileNamePtr(infilename);
else
filename = infilename;
fnlen = strlen(filename) + 1;
if (incls->numincls >= incls->maxincls) {
incls->maxincls += 16;
incls->files = xrealloc("include list", incls->files, sizeof(InclFile) * incls->maxincls);
}
f = &incls->files[incls->numincls];
f->filenameoffs = incls->bufpos;
f->syspath = syspath;
f->accesspath = accesspath;
if (globalpath) {
f->globalpath = globalpath;
} else if (accesspath) {
f->globalpath = FindOrAddGlobalInclPath(incls->allPaths, accesspath->spec);
} else {
OS_MakeFileSpec(infilename, &spec);
f->globalpath = FindOrAddGlobalInclPath(incls->allPaths, &spec.path);
}
f->specialpath = Deps_GetSpecialAccessPath();
if (incls->bufpos + fnlen > incls->buflen) {
incls->buflen += 1024;
incls->buffer = xrealloc("include list", incls->buffer, incls->buflen);
}
strcpy(&incls->buffer[incls->bufpos], filename);
incls->bufpos += fnlen;
*index = incls->numincls++;
}
Boolean Incls_FindFileInPaths(Incls *incls, char *filename, Boolean fullsearch, OSSpec *spec, SInt32 *inclidx) {
Boolean found;
InclFile *incl;
Boolean foundglobal;
Path *globalpath;
Path *accesspath;
Path *specialpath;
Boolean userpath;
char rel_path[256];
found = 0;
if (optsCompiler.includeSearch == 3 && fullsearch)
SetSpecialAccessPathFromIncludeStackTOS();
*inclidx = -1;
foundglobal = QuickFindFileInIncls(incls, fullsearch, filename, spec, inclidx, &incl);
if (foundglobal) {
if (incl->specialpath == specialAccessPath && incl->syspath && !fullsearch)
found = 1;
else if (!incl->accesspath)
foundglobal = 0;
}
if (!found) {
accesspath = globalpath = NULL;
userpath = fullsearch;
if (OS_IsFullPath(filename)) {
found = !OS_MakeFileSpec(filename, spec) && !OS_Status(spec);
accesspath = globalpath = specialpath = NULL;
} else {
specialpath = Deps_GetSpecialAccessPath();
globalpath = specialpath;
if (specialpath) {
found = _FindFileInPath(specialpath, filename, &globalpath, spec);
accesspath = NULL;
}
if (!found && foundglobal && incl->syspath && !fullsearch) {
globalpath = incl->globalpath;
accesspath = incl->accesspath;
specialpath = NULL;
MakeInclFileSpec(incls, *inclidx, spec);
found = 1;
}
if (!found && fullsearch) {
userpath = 1;
globalpath = NULL;
found = FindFileInPaths(&incls->targ->userPaths, filename, &accesspath, spec);
}
if (!found) {
userpath = 0;
globalpath = NULL;
found = FindFileInPaths(&incls->targ->sysPaths, filename, &accesspath, spec);
}
if (!found) {
specialpath = Deps_GetSpecialAccessPath();
globalpath = specialpath;
if (!found && MakeFrameworkPath(rel_path, filename, specialpath)) {
filename = rel_path;
found = FindFileInPaths(&FrameworkPaths, filename, &globalpath, spec);
}
}
}
if (found && *inclidx < 0)
AddFileToIncls(incls, filename, !userpath, accesspath, globalpath, specialpath, inclidx);
}
return found;
}
Boolean Deps_Initialize(Deps *deps, Incls *incls) {
deps->numDeps = 0;
deps->maxDeps = 0;
deps->list = NULL;
deps->incls = incls;
return 1;
}
void Deps_Terminate(Deps *deps) {
if (deps->list)
xfree(deps->list);
}
int Deps_ChangeSpecialAccessPath(OSSpec *srcfss, Boolean initialize) {
static OSSpec *currentsrcfss;
OSPathSpec pathspec;
OSPathSpec *pathspecptr;
if (initialize && srcfss)
currentsrcfss = srcfss;
switch (optsCompiler.includeSearch) {
case IncludeSearch_Type2:
specialAccessPath = NULL;
return 1;
case IncludeSearch_Type0:
if (!initialize)
return 1;
OS_GetCWD(&pathspec);
pathspecptr = &pathspec;
break;
case IncludeSearch_Type1:
if (!initialize)
return 1;
case IncludeSearch_Type3:
if (srcfss) {
pathspecptr = &srcfss->path;
} else if (currentsrcfss) {
pathspecptr = &currentsrcfss->path;
} else {
OS_GetCWD(&pathspec);
pathspecptr = &pathspec;
}
break;
default:
DO_INTERNAL_ERROR(468, "Unhandled include file search type (%d)\n", optsCompiler.includeSearch);
}
specialAccessPath = FindOrAddGlobalInclPath(gTarg->incls.allPaths, pathspecptr);
if (optsCmdLine.verbose > 2)
CLReport(CLStr105, OS_PathSpecToString(pathspecptr, STSbuf, sizeof(STSbuf)));
return 1;
}
Path *Deps_GetSpecialAccessPath(void) {
return specialAccessPath;
}
static void SetSpecialAccessPathFromIncludeStackTOS(void) {
// does not match, some registers are in the wrong order
OSSpec spec;
SInt16 index;
char *fnameptr;
VFile *vf;
if (optsCompiler.includeSearch == IncludeSearch_Type3 && CLT_filesp && CLT_filestack) {
if (*CLT_filesp >= 0) {
index = *CLT_filesp;
while (index) {
if (!(*CLT_filestack)[index])
break;
OS_FSSpec_To_OSSpec(&(*CLT_filestack)[index--]->textfile, &spec);
fnameptr = OS_GetFileNamePtr(OS_NameSpecToString(&spec.name, STSbuf, sizeof(STSbuf)));
vf = VFiles_Find(gTarg->virtualFiles, fnameptr);
if (!vf) {
if (!specialAccessPath || !OS_EqualPathSpec(&spec.path, specialAccessPath->spec)) {
Deps_ChangeSpecialAccessPath(&spec, 0);
return;
}
return;
}
}
}
Deps_ChangeSpecialAccessPath(NULL, 0);
}
}
static Boolean FindDepFile(Deps *deps, SInt32 incl) {
int idx;
for (idx = 0; idx < deps->numDeps; idx++) {
if (SameIncl(&gTarg->incls, deps->list[idx], incl))
return 1;
}
return 0;
}
static void AddDepFile(Deps *deps, SInt32 incl, SInt16 dependencyType) {
if (deps->numDeps >= deps->maxDeps) {
deps->maxDeps += 16;
deps->list = xrealloc("dependency list", deps->list, sizeof(SInt32) * deps->maxDeps);
}
deps->list[deps->numDeps++] = incl;
}
void Deps_AddDependency(Deps *deps, SInt32 incl, OSSpec *spec, Boolean unk, SInt16 dependencyType, Boolean *alreadyincluded) {
Boolean included;
if (incl < 0) {
AddFileToIncls(
&gTarg->incls,
OS_SpecToString(spec, STSbuf, sizeof(STSbuf)),
0,
NULL, NULL, NULL,
&incl);
}
included = FindDepFile(deps, incl);
if (!included) {
if (!(optsCompiler.depsOnlyUserFiles ? IsSysIncl(deps->incls, incl) : 0))
AddDepFile(deps, incl, dependencyType);
}
if (alreadyincluded)
*alreadyincluded = included;
}
static char *EscapeName(Boolean spaces, char *escbuf, char *path) {
char *ret;
if (!spaces)
return path;
ret = escbuf;
while (*path) {
if (*path == ' ')
*(escbuf++) = '\\';
*(escbuf++) = *(path++);
}
*escbuf = 0;
return ret;
}
void Deps_ListDependencies(Incls *incls, File *file, OSHandle *h) {
Boolean spaces;
int idx;
char linebuf[512];
char outfilename[256];
int totdeps;
char path[256];
char escbuf[320];
OSSpec spec;
#define LIST_DEP(format, name, ...) \
do { \
sprintf(linebuf, format, spaces ? "" : "", EscapeName(spaces, escbuf, (name)), spaces ? "" : "", __VA_ARGS__); \
if (OS_AppendHandle(h, linebuf, strlen(linebuf))) goto memFail; \
} while (0)
if (!OS_NewHandle(0, h)) {
totdeps = file->deps.numDeps;
OS_SpecToStringRelative(&file->outfss, NULL, outfilename, sizeof(outfilename));
if (outfilename[0]) {
spaces = strchr(outfilename, ' ') != NULL;
LIST_DEP("%s%s%s%s ", outfilename, ":");
spaces = strchr(file->srcfilename, ' ') != NULL;
LIST_DEP("%s%s%s %s\n", file->srcfilename, totdeps ? "\\" : "");
} else {
spaces = strchr(file->srcfilename, ' ') != NULL;
LIST_DEP("%s%s%s%s %s\n", file->srcfilename, ":", totdeps ? "\\" : "");
}
for (idx = 0; idx < file->deps.numDeps; idx++) {
totdeps--;
MakeInclFileSpec(incls, file->deps.list[idx], &spec);
OS_SpecToString(&spec, path, sizeof(path));
spaces = strchr(path, ' ') != NULL;
LIST_DEP("\t%s%s%s %s\n", path, totdeps ? "\\" : "");
}
} else {
memFail:
fprintf(stderr, "\n*** Out of memory\n");
exit(-23);
}
}