#include "cmdline.h" // TODO check where this should be! Paths FrameworkPaths; Frameworks FrameworkInfo; Path *Path_Init(const OSPathSpec *dir, Path *path) { path->spec = xmalloc(NULL, sizeof(OSPathSpec)); *path->spec = *dir; path->recursive = NULL; path->dirlist = NULL; path->flags = 0; return path; } Path *Path_New(const OSPathSpec *dir) { Path *path; path = xmalloc(NULL, sizeof(Path)); return Path_Init(dir, path); } void Path_Free(Path *path) { if (path) { if (path->spec) xfree(path->spec); if (path->recursive) { Paths_Terminate(path->recursive); xfree(path->recursive); } xfree(path); } } Boolean Paths_Initialize(Paths *paths) { OS_ASSERT(52, paths != NULL); memset(paths, 0, sizeof(Paths)); paths->pathsArray = NULL; return 1; } Boolean Paths_Terminate(Paths *paths) { UInt16 index; OS_ASSERT(63, paths != NULL); if (paths->pathsArray) { for (index = 0; index < paths->pathsCount; index++) Path_Free(paths->pathsArray[index]); xfree(paths->pathsArray); } paths->pathsArray = NULL; return 1; } static Boolean Paths_GrowPaths(Paths *paths, UInt16 *index) { Path **newArray; OS_ASSERT(84, paths != NULL); if (paths->pathsCount >= paths->arraySize) { paths->arraySize += 20; newArray = xrealloc("access paths", paths->pathsArray, sizeof(Path *) * paths->arraySize); paths->pathsArray = newArray; } *index = paths->pathsCount++; return 1; } Boolean Paths_AddPath(Paths *paths, Path *path) { UInt16 ni; if (Paths_GrowPaths(paths, &ni)) { paths->pathsArray[ni] = path; return 1; } else { return 0; } } Boolean Paths_InsertPath(Paths *paths, UInt16 index, Path *path) { UInt16 ni; if (Paths_GrowPaths(paths, &ni)) { if (index > ni) { index = (ni != 0) ? (ni - 1) : 0; } memmove(&paths->pathsArray[index + 1], &paths->pathsArray[index], sizeof(Path *) * (paths->pathsCount - index)); paths->pathsArray[index] = path; return 1; } else { return 0; } } Boolean Paths_RemovePath(Paths *paths, UInt16 index) { if (index >= paths->pathsCount) return 0; memmove(&paths->pathsArray[index], &paths->pathsArray[index + 1], sizeof(Path *) * (paths->pathsCount - index - 1)); paths->pathsCount--; return 1; } Boolean Paths_DeletePath(Paths *paths, UInt16 index) { if (index >= paths->pathsCount) return 0; Path_Free(paths->pathsArray[index]); return Paths_RemovePath(paths, index); } Path *Paths_GetPath(Paths *paths, UInt16 pathnum) { OS_ASSERT(151, paths != NULL); if (pathnum < paths->pathsCount) return paths->pathsArray[pathnum]; else return NULL; } UInt16 Paths_Count(const Paths *paths) { OS_ASSERT(161, paths != NULL); return paths->pathsCount; } Boolean Paths_FindPath(const Paths *paths, const Path *path) { UInt16 idx; OS_ASSERT(169, paths != NULL); for (idx = 0; idx < paths->pathsCount; idx++) { if (paths->pathsArray[idx] == path) return 1; } return 0; } Path *Paths_FindPathSpec(const Paths *paths, const OSPathSpec *dir) { UInt16 idx; Path *path; OS_ASSERT(182, paths != NULL); for (idx = 0; idx < paths->pathsCount; idx++) { path = paths->pathsArray[idx]; if (OS_EqualPathSpec(path->spec, dir)) return path; } return NULL; } static Boolean GatherRecurse(Paths *list, Path *path) { int err; OSOpenedDir rf; OSSpec ent; int count; char filename[64]; Boolean isfile; char *nptr; char *eptr; UInt16 added; Path *nw; count = 0; if (CheckForUserBreak()) return 1; err = OS_OpenDir(path->spec, &rf); while (!err) { err = OS_ReadDir(&rf, &ent, filename, &isfile); if (!err) { if (!isfile) { nw = Path_New(&ent.path); nptr = OS_GetFileNamePtr(filename); eptr = nptr + strlen(nptr) - 1; if (eptr[0] == OS_PATHSEP) eptr--; if (eptr > nptr && *nptr == '(' && *eptr == ')') continue; if (!Paths_AddPath(list, nw)) break; added = Paths_Count(list) - 1; if (!GatherRecurse(list, nw)) Paths_DeletePath(list, added); } else { if (!(++count % 50) && CheckForUserBreak()) return 0; } } } OS_CloseDir(&rf); return count > 0; } Boolean Paths_GatherRecurse(Path *path) { path->recursive = xcalloc(NULL, sizeof(Paths)); GatherRecurse(path->recursive, path); return Paths_Count(path->recursive) != 0; } int Paths_CountRecurse(Paths *paths) { UInt16 idx; int mine; Path *path; mine = Paths_Count(paths); for (idx = 0; idx < mine; idx++) { path = Paths_GetPath(paths, idx); OS_ASSERT(336, path); if (path->recursive) mine += Paths_CountRecurse(path->recursive); } return mine; } static void CopyRecurseFSS(FSSpec **list, Paths *paths, UInt16 *count) { UInt16 idx; OSSpec spec; Path *path; for (idx = 0; idx < Paths_Count(paths); idx++) { path = Paths_GetPath(paths, idx); OS_ASSERT(353, path && *count > 0); OS_MakeSpecWithPath(path->spec, NULL, 0, &spec); OS_ASSERT(355, OS_OSSpec_To_FSSpec(&spec, *list)); (*list)++; (*count)--; if (path->recursive) CopyRecurseFSS(list, path->recursive, count); } } void Paths_CopyRecurseFSS(FSSpec *list, Paths *paths, UInt16 count) { CopyRecurseFSS(&list, paths, &count); OS_ASSERT(367, count == 0); } static Boolean Frameworks_Initialize(Frameworks *fws) { OS_ASSERT(405, fws != NULL); memset(fws, 0, sizeof(Frameworks)); fws->fwsArray = NULL; return 1; } static Boolean Frameworks_Grow(Frameworks *fws, UInt16 *index) { Paths_FWInfo **newArray; OS_ASSERT(418, fws != NULL); if (fws->fwsCount >= fws->arraySize) { fws->arraySize += 20; newArray = xrealloc("access frameworks", fws->fwsArray, sizeof(Paths_FWInfo *) * fws->arraySize); fws->fwsArray = newArray; } *index = fws->fwsCount++; return 1; } static Boolean Frameworks_Add(Frameworks *fws, Paths_FWInfo *info) { UInt16 ni; if (Frameworks_Grow(fws, &ni)) { fws->fwsArray[ni] = info; return 1; } else { return 0; } } static Paths_FWInfo *Framework_Init(OSSpec *dir, const char *name, const char *version, Paths_FWInfo *info, Path *p, Boolean hidden) { info->fileSpec = *dir; if (version && version[0]) strncpy(info->version.s, version, sizeof(info->version.s)); else info->version.s[0] = 0; strncpy(info->name.s, name, sizeof(info->name.s)); info->path = p; info->hidden = hidden; return info; } static Paths_FWInfo *Framework_New(OSSpec *dir, const char *name, const char *version, Path *p, Boolean hidden) { Paths_FWInfo *info; info = xmalloc(NULL, sizeof(Paths_FWInfo)); return Framework_Init(dir, name, version, info, p, hidden); } static Boolean CheckForFileInFrameworkDir(char *out, const char *framework_path, OSPathSpec *osps, const char *fname) { int err; OSSpec oss; sprintf(out, "%s/%s", framework_path, fname); err = OS_MakeSpecWithPath(osps, out, 0, &oss); if (err == 0 && OS_IsFile(&oss)) return 1; sprintf(out, "%s/Headers/%s", framework_path, fname); err = OS_MakeSpecWithPath(osps, out, 0, &oss); if (err == 0 && OS_IsFile(&oss)) return 1; sprintf(out, "%s/Resources/%s", framework_path, fname); err = OS_MakeSpecWithPath(osps, out, 0, &oss); if (err == 0 && OS_IsFile(&oss)) return 1; sprintf(out, "%s/Resources/%s", framework_path, fname); err = OS_MakeSpecWithPath(osps, out, 0, &oss); if (err == 0 && OS_IsFile(&oss)) return 1; return 0; } static Boolean CheckForFileInFramework(char *out, int i, const char *fname) { Paths_FWInfo *info; char framework_path[256]; info = Frameworks_GetInfo(i); if (strlen(info->version.s)) sprintf(framework_path, "%s.framework/Versions/%s", info->name.s, info->version.s); else sprintf(framework_path, "%s.framework", info->name.s); if (CheckForFileInFrameworkDir(out, framework_path, info->path->spec, fname)) return 1; else return 0; } Boolean MakeFrameworkPath(char *out, const char *filename, Path *globalpath) { Paths_FWInfo *info; int err; char *end; char *fname; char framework_name[256]; char framework_path[256]; const char *s; char *d; int i; int n; n = Frameworks_GetCount(); end = strchr(filename, OS_PATHSEP); if (!end) { for (i = 0; i < n; i++) { info = Frameworks_GetInfo(i); if (!info->hidden && CheckForFileInFramework(out, i, filename)) return 1; } return 0; } fname = end + 1; s = filename; d = framework_name; while (s < end) *(d++) = *(s++); *d = 0; for (i = 0; i < n; i++) { if (!strcmp(Frameworks_GetInfo(i)->name.s, framework_name)) { return CheckForFileInFramework(out, i, fname) != 0; } } if (globalpath) { OSSpec oss; sprintf(framework_path, "../Frameworks/%s.framework", framework_name); err = OS_MakeSpecWithPath(globalpath->spec, framework_path, 0, &oss); if (!err && OS_IsDir(&oss)) { if (CheckForFileInFrameworkDir(out, framework_path, globalpath->spec, fname)) return 1; } } n = Paths_Count(&FrameworkPaths); sprintf(framework_path, "%s.framework", framework_name); for (i = 0; i < n; i++) { OSSpec oss; Path *p; p = Paths_GetPath(&FrameworkPaths, i); err = OS_MakeSpecWithPath(p->spec, framework_path, 0, &oss); if (!err && OS_IsDir(&oss)) { if (CheckForFileInFrameworkDir(out, framework_path, p->spec, fname)) { Frameworks_AddFramework(framework_name, NULL, 1); return 1; } } } return 0; } void Frameworks_AddPath(const OSPathSpec *oss) { Paths_AddPath(&FrameworkPaths, Path_New(oss)); } int Frameworks_AddFramework(const char *name, const char *version, Boolean hidden) { char fullname[256]; int i; Path *p; int n_paths; OSSpec oss; int err; sprintf(fullname, "%s.framework", name); n_paths = Paths_Count(&FrameworkPaths); for (i = 0; i < n_paths; i++) { p = Paths_GetPath(&FrameworkPaths, i); err = OS_MakeSpecWithPath(p->spec, fullname, 0, &oss); if (!err && OS_IsDir(&oss)) { if (Frameworks_Add(&FrameworkInfo, Framework_New(&oss, name, version, p, hidden))) { if (version && strlen(version)) { sprintf(fullname, "Versions/%s/Frameworks", version); err = OS_MakeSpecWithPath(&oss.path, fullname, 0, &oss); } else { err = OS_MakeSpecWithPath(&oss.path, "Frameworks", 0, &oss); } if (!err && OS_IsDir(&oss)) Frameworks_AddPath(&oss.path); return 1; } } } return 0; } void Framework_GetEnvInfo(void) { char path[256]; char *env; char *ptr; OSSpec spec; char name[64]; char version[16]; int err; Boolean is_file; OS_ASSERT(672, Paths_Initialize(&FrameworkPaths) == 1); OS_ASSERT(673, Frameworks_Initialize(&FrameworkInfo) == 1); env = getenv("MWFrameworkPaths"); if (env) { while (*env) { ptr = path; while (*env && *env != ':' && (ptr + 1) < &path[sizeof(path)]) *(ptr++) = *(env++); *ptr = 0; while (*env && *env == ':') env++; if (path[0]) { if (strlen(path) >= sizeof(path)) { CLReportError(CLStr64, sizeof(path), path); } else { err = OS_MakeSpec(path, &spec, &is_file); if (!is_file && !err) { Frameworks_AddPath(&spec.path); } else { CLReportError(CLStr23, path); } } } } } env = getenv("MWFrameworkVersions"); if (env) { while (*env) { ptr = name; while (*env && *env != ':' && (ptr + 1) < &name[sizeof(name)]) *(ptr++) = *(env++); *ptr = 0; while (*env && *env == ':') env++; ptr = version; while (*env && *env != ',' && (ptr + 1) < &version[sizeof(version)]) *(ptr++) = *(env++); *ptr = 0; while (*env && *env == ',') env++; if (name[0]) Frameworks_AddFramework(name, version, 0); } } } int Frameworks_GetCount(void) { return FrameworkInfo.fwsCount; } Paths_FWInfo *Frameworks_GetInfo(int which) { OS_ASSERT(762, FrameworkInfo.fwsArray); OS_ASSERT(763, FrameworkInfo.fwsCount > which); return FrameworkInfo.fwsArray[which]; }