#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 = ¤tsrcfss->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(105, 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); } }