mirror of https://git.wuffs.org/MWCC
536 lines
12 KiB
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;
|
|
}
|