mirror of https://git.wuffs.org/MWCC
526 lines
13 KiB
C
526 lines
13 KiB
C
#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) {
|
|
#line 52
|
|
OPTION_ASSERT(paths != NULL);
|
|
|
|
memset(paths, 0, sizeof(Paths));
|
|
paths->pathsArray = NULL;
|
|
return 1;
|
|
}
|
|
|
|
Boolean Paths_Terminate(Paths *paths) {
|
|
UInt16 index;
|
|
|
|
#line 63
|
|
OPTION_ASSERT(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;
|
|
|
|
#line 84
|
|
OPTION_ASSERT(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) {
|
|
#line 151
|
|
OPTION_ASSERT(paths != NULL);
|
|
|
|
if (pathnum < paths->pathsCount)
|
|
return paths->pathsArray[pathnum];
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
UInt16 Paths_Count(const Paths *paths) {
|
|
#line 161
|
|
OPTION_ASSERT(paths != NULL);
|
|
|
|
return paths->pathsCount;
|
|
}
|
|
|
|
Boolean Paths_FindPath(const Paths *paths, const Path *path) {
|
|
UInt16 idx;
|
|
|
|
#line 169
|
|
OPTION_ASSERT(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;
|
|
|
|
#line 182
|
|
OPTION_ASSERT(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);
|
|
#line 336
|
|
OPTION_ASSERT(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);
|
|
#line 353
|
|
OPTION_ASSERT(path && *count > 0);
|
|
OS_MakeSpecWithPath(path->spec, NULL, 0, &spec);
|
|
#line 355
|
|
OPTION_ASSERT(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);
|
|
#line 367
|
|
OPTION_ASSERT(count == 0);
|
|
}
|
|
|
|
static Boolean Frameworks_Initialize(Frameworks *fws) {
|
|
#line 405
|
|
OPTION_ASSERT(fws != NULL);
|
|
|
|
memset(fws, 0, sizeof(Frameworks));
|
|
fws->fwsArray = NULL;
|
|
return 1;
|
|
}
|
|
|
|
static Boolean Frameworks_Grow(Frameworks *fws, UInt16 *index) {
|
|
Paths_FWInfo **newArray;
|
|
|
|
#line 418
|
|
OPTION_ASSERT(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() {
|
|
char path[256];
|
|
char *env;
|
|
char *ptr;
|
|
OSSpec spec;
|
|
char name[64];
|
|
char version[16];
|
|
int err;
|
|
Boolean is_file;
|
|
|
|
#line 672
|
|
OPTION_ASSERT(Paths_Initialize(&FrameworkPaths) == 1);
|
|
OPTION_ASSERT(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(64, sizeof(path), path);
|
|
} else {
|
|
err = OS_MakeSpec(path, &spec, &is_file);
|
|
if (!is_file && !err) {
|
|
Frameworks_AddPath(&spec.path);
|
|
} else {
|
|
CLReportError(23, 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() {
|
|
return FrameworkInfo.fwsCount;
|
|
}
|
|
|
|
Paths_FWInfo *Frameworks_GetInfo(int which) {
|
|
#line 762
|
|
OPTION_ASSERT(FrameworkInfo.fwsArray);
|
|
OPTION_ASSERT(FrameworkInfo.fwsCount > which);
|
|
return FrameworkInfo.fwsArray[which];
|
|
}
|