MWCC/command_line/C++_Parser/Src/Library/ParserHelpers.c

536 lines
12 KiB
C

#include "parser.h"
#include "cmdline.h"
#include <errno.h>
SInt16 lastStage;
Boolean dashIMinusMovesPaths;
Boolean usedDashIMinus;
Boolean namingSysPaths;
static char STSbuf[256];
int FindFileInPath(const char *filename, OSSpec *fss) {
CWFileInfo fi;
CWResult result;
fi.fullsearch = 1;
fi.dependencyType = 0;
fi.suppressload = 1;
fi.isdependentoffile = kCurrentCompiledFile;
result = CWFindAndLoadFile(parseopts.context, filename, &fi);
if (!result) {
OS_FSSpec_To_OSSpec(&fi.filespec, fss);
return 1;
} else {
return 0;
}
}
char *GetEnvVar(const char *name, Boolean warn, const char **match) {
const char *nptr;
const char *last;
char *ret;
nptr = name;
last = name;
while (*nptr) {
ret = getenv(nptr);
if (ret) {
if (match)
*match = nptr;
return ret;
}
last = nptr;
nptr = &nptr[1 + strlen(nptr)];
}
if (warn)
CLPReportWarning(CLPStr52, last);
*match = 0;
return 0;
}
static Boolean MatchesExtension(const char *list, const char *filename) {
char *fn;
const char *eptr;
const char *ptr;
fn = OS_GetFileNamePtr((char *) filename);
eptr = strrchr(fn, '.');
if (!eptr)
return 0;
if (!list)
return 1;
ptr = eptr;
while (*list) {
if (*list == '|' && !*ptr)
return 1;
if (my_tolower(*list) == my_tolower(*ptr)) {
list++;
ptr++;
continue;
}
while (*list && *list != '|')
list++;
if (*list)
list++;
ptr = eptr;
}
return !*list && !*ptr;
}
int Opt_AddAccessPath(const char *opt, void *var, const char *arg, int flags) {
OSPathSpec spec;
int err;
arg = arg ? arg : opt;
if (!arg)
return 0;
if (!arg[0])
return 1;
if (strlen(arg) >= 256) {
CLPReportError(CLPStr13, arg + strlen(arg) - 32, 256);
return 0;
}
err = OS_MakePathSpec(0, arg, &spec);
if (err == ENOENT || err == ENOENT) {
CLPReportWarning(CLPStr45, arg);
return 1;
} else if (err != 0) {
CLPOSAlert(CLPStr45, err, arg);
return 1;
}
// this 'if' gets optimised unnecessarily
if (!AddAccessPath(&spec, namingSysPaths, 0, var != NULL))
return 0;
else
return 1;
}
int Opt_AddFrameworkPath(const char *opt, void *var, const char *arg, int flags) {
OSPathSpec spec;
int err;
arg = arg ? arg : opt;
if (!arg)
return 0;
if (!arg[0])
return 1;
if (strlen(arg) >= 256) {
CLPReportError(CLPStr13, arg + strlen(arg) - 32, 256);
return 0;
}
err = OS_MakePathSpec(0, arg, &spec);
if (err == ENOENT || err == ENOENT) {
CLPReportWarning(CLPStr45, arg);
return 1;
} else if (err != 0) {
CLPOSAlert(CLPStr45, err, arg);
return 1;
} else {
Frameworks_AddPath(&spec);
return 1;
}
}
int Opt_AddFramework(const char *opt, void *var, const char *arg, int flags) {
if (!Frameworks_AddFramework(arg ? arg : opt, 0, 0))
return 0;
else
return 1;
}
void ListParseMessage(void (*errprint)(const char *, va_list), const char *envvar, SInt16 id, ...) {
char buf[1024];
va_list ap;
if (envvar && envvar[0])
sprintf(buf, "In environment variable '%s':\n", envvar);
else
buf[0] = 0;
CLPGetErrorString(id, buf + strlen(buf));
va_start(ap, id);
errprint(buf, ap);
va_end(ap);
}
int AddAccessPathList(const char *list, char sep1, char sep2, int source, char *text, Boolean system, SInt32 position, Boolean recursive) {
char tmp[256];
Boolean recurse;
OSPathSpec spec;
int err;
short type;
char *ptr;
type = (Boolean) ((system == 1) ? 1 : 0) | (!source ? 0 : 2);
recurse = (list[0] == '+');
if (recurse)
++list;
if (!strchr(list, sep1))
sep1 = sep2;
while (*list) {
ptr = tmp;
while (*list && *list != sep1 && (ptr + 1) < &tmp[256]) {
*(ptr++) = *(list++);
}
*ptr = 0;
if ((ptr + 1) >= &tmp[256]) {
ListParseMessage(
CLPReportError_V,
(source == 1) ? text : NULL,
CLPStr9,
tmp,
tmp + strlen(tmp) - 16,
256);
return 0;
}
err = OS_MakePathSpec(0, tmp, &spec);
if (err) {
ListParseMessage(
CLPReportWarning_V,
(source == 1) ? text : NULL,
CLPStr45,
tmp);
} else {
AddAccessPath(&spec, type, position, recurse ^ recursive);
}
if (*list)
++list;
recurse = *list == '+';
if (recurse)
++list;
}
return 1;
}
int Opt_FindAndAddFile(const char *opt, void *var, const char *arg, int flags) {
OSSpec spec;
int err;
Boolean isfile;
arg = arg ? arg : opt;
if (!arg)
return 0;
if (!*arg)
return 1;
parseopts.userSpecifiedFiles++;
err = OS_MakeSpec(arg, &spec, &isfile);
if (!err)
err = OS_Status(&spec);
if (!err && !isfile) {
CLPReportError(CLPStr47, arg);
parseopts.unusedFiles++;
return 0;
} else if (err && err != ENOENT) {
CLPOSAlert(CLPStr44, err, arg);
parseopts.unusedFiles++;
return 0;
} else if (err && parseopts.alwaysUsePaths) {
err = FindFileInPath(arg, &spec) ? 0 : ENOENT;
}
if (err) {
CLPReportError(CLPStr44, arg);
parseopts.unusedFiles++;
return 0;
}
if (var && !MatchesExtension((const char *) var, arg))
CLPReportWarning(CLPStr76, arg, var);
if (!AddFileToProject(&spec, lastStage, parseopts.lastoutputname, 1, -1)) {
parseopts.unusedFiles++;
return 0;
} else {
parseopts.lastoutputname[0] = 0;
return 1;
}
}
int Opt_FindAndAddFileRef(const char *opt, void *var, const char *arg) {
OSSpec spec;
int err;
Boolean isfile;
arg = arg ? arg : opt;
if (!arg)
return 0;
if (!*arg)
return 1;
parseopts.userSpecifiedFiles++;
if (var && !MatchesExtension((const char *) var, arg))
CLPReportWarning(CLPStr76, arg, var);
err = OS_MakeSpec(arg, &spec, &isfile);
if (!err)
err = OS_Status(&spec);
if (!err && !isfile) {
CLPReportError(CLPStr47, arg);
parseopts.unusedFiles++;
return 0;
} else if (err && parseopts.alwaysUsePaths) {
err = FindFileInPath(arg, &spec) ? 0 : ENOENT;
}
if (!AddFileToProject(&spec, 0, 0, err == 0, -1)) {
parseopts.unusedFiles++;
return 0;
} else {
return AddAccessPath(&spec.path, 1, -1, 0) != 0;
}
}
int Opt_AddUnixLibraryFile(const char *opt, void *var, const char *name) {
OSSpec spec;
Boolean failed;
const char *eptr;
const char *eend;
char tmpname[64];
if (strlen(name) >= 56) {
CLPReportError(CLPStr13, name + strlen(name) - 32, 64);
return 0;
}
failed = 1;
if (!var)
var = ".lib|.a";
eptr = (const char *) var;
while (eptr && *eptr) {
eend = eptr;
while (*eend && *eend != '|')
++eend;
sprintf(tmpname, "lib%s%*.*s", name, eend - eptr, eend - eptr, eptr);
if (FindFileInPath(tmpname, &spec)) {
failed = 0;
break;
}
if (*eend)
eptr = eend + 1;
else
eptr = eend;
}
if (failed) {
failed = !FindFileInPath(name, &spec);
if (failed)
CLPReportError(CLPStr49, name, var, name);
}
if (!failed) {
if (!AddFileToProject(&spec, 0, 0, 1, -1)) {
parseopts.unusedFiles++;
failed = 1;
}
}
return !failed;
}
int AddFileList(const char *list, char sep1, char sep2, int source, char *text, SInt32 position) {
char tmp[256];
OSSpec spec;
char *ptr;
if (!strchr(list, sep1))
sep1 = sep2;
while (*list) {
ptr = tmp;
while (*list && *list != sep1 && (ptr + 1) < &tmp[256]) {
*(ptr++) = *(list++);
}
*ptr = 0;
if ((ptr + 1) >= &tmp[256]) {
ListParseMessage(
CLPReportError_V,
(source == 1) ? text : 0,
CLPStr9,
tmp,
tmp + strlen(tmp) - 16,
256
);
return 0;
}
if (!FindFileInPath(tmp, &spec)) {
if (OS_IsDir(&spec)) {
ListParseMessage(
CLPReportError_V,
(source == 1) ? text : 0,
CLPStr16,
tmp
);
} else {
ListParseMessage(
CLPReportWarning_V,
(source == 1) ? text : 0,
CLPStr44,
tmp
);
}
} else {
AddFileToProject(&spec, 0, 0, 1, position);
}
if (*list)
++list;
}
return 1;
}
int IsFileInOutputDirectory(const OSSpec *file) {
OSPathSpec outdir;
GetOutputFileDirectory(&outdir);
return OS_EqualPathSpec(&outdir, &file->path);
}
void GetCFileNameInOutputDirectory(const char *input, char *name, int maxlen) {
char filename[64];
OSSpec spec;
int err;
err = OS_MakeFileSpec(input, &spec);
if (err) {
CLPOSAlert(CLPStr64, err, input);
name[0] = 0;
return;
}
if (!IsFileInOutputDirectory(&spec)) {
CLPReportWarning(CLPStr61, OS_SpecToStringRelative(&spec, 0, STSbuf, sizeof(STSbuf)));
}
OS_NameSpecToString(&spec.name, filename, 256);
if (strlen(filename) >= maxlen) {
CLPReportWarning(CLPStr65, filename, maxlen - 1);
filename[maxlen - 1] = 0;
}
strcpy(name, filename);
}
void GetPFileNameInOutputDirectory(const char *input, unsigned char *name, int len) {
GetCFileNameInOutputDirectory(input, (char *) name, len);
c2pstr((char *) name);
}
void AddStringLenToHandle(Handle *h, const char *str, int len) {
SInt32 old;
if (!*h) {
if ((*h = NewHandle(len + 1))) {
HLock(*h);
memcpy(**h, str, len);
(**h)[len] = 0;
HUnlock(*h);
} else {
exit(-23);
}
} else {
old = GetHandleSize(*h) - 1;
SetHandleSize(*h, old + len + 1);
if (MemError() == noErr) {
HLock(*h);
memcpy(**h + old, str, len);
(**h)[old + len] = 0;
HUnlock(*h);
} else {
exit(-23);
}
}
}
void AddStringToHandle(Handle *h, const char *str) {
AddStringLenToHandle(h, str, strlen(str));
}
int Opt_PrintVersion(const char *opt, void *var, const char *arg, int flags) {
ShowVersion(0);
return 1;
}
void GetFirstSourceFilenameBase(char *buffer, char *defaul) {
int cnt;
OSSpec spec;
char compiler[32];
int x;
char *ext;
cnt = GetFileCount();
for (x = 0; x < cnt; x++) {
if (GetFileInfo(x, &spec, compiler)) {
if (compiler[0]) {
if (!strstr(compiler, "Lib")) {
OS_NameSpecToString(&spec.name, buffer, 256);
ext = strrchr(buffer, '.');
if (ext)
*ext = 0;
memmove(buffer, buffer, strlen(buffer) + 1);
return;
}
}
}
}
strcpy(buffer, defaul);
}
int Opt_SavePrefs(const char *opt, void *var, const char *arg, int flags) {
Parser_StorePanels(parseopts.context);
return 1;
}
int ParseNumber(const char *arg, Boolean emit_error, SInt32 *ret, const char **endptr) {
char *end;
if (arg[0] == '0' && (arg[1] == 'x' || arg[1] == 'X')) {
*ret = strtol(arg + 2, &end, 16);
} else if (arg[0] == '0') {
*ret = strtol(arg + 1, &end, 8);
} else {
*ret = strtol(arg, &end, 10);
}
if (endptr)
*endptr = end;
if (*end && emit_error) {
CLPReportError(CLPStr5, "", arg);
return 0;
}
return 1;
}
int Opt_MaybeMoveAccessPaths(const char *opt, void *var, const char *arg, int flags) {
if (dashIMinusMovesPaths && !usedDashIMinus)
MoveSystemPathsIntoUserList();
return 1;
}