MWCC/unsorted/Option.c

1135 lines
34 KiB
C
Raw Normal View History

#include "parser.h"
2022-10-07 19:02:27 +00:00
#define MAXSTACK 8
static OptionList *optionlists[32];
int numoptionlists;
static OptionList internalset;
static OptionList legalset;
int numinternalset;
int numlegalset;
int maxlegalset;
char curopt[1024];
Opt48 oStack[8];
int oStackPtr;
2022-10-07 19:02:27 +00:00
enum {
ARGFLAG_1 = 1,
ARGFLAG_2 = 2,
ARGFLAG_4 = 4,
ARGFLAG_8 = 8,
ARGFLAG_10 = 0x10,
ARGFLAG_20 = 0x20,
ARGFLAG_40 = 0x40,
ARGFLAG_80 = 0x80
};
enum {
ARGSPELLFLAG_1 = 1,
ARGSPELLFLAG_2 = 2,
ARGSPELLFLAG_4 = 4,
ARGSPELLFLAG_8 = 8,
ARGSPELLFLAG_10 = 0x10,
ARGSPELLFLAG_20 = 0x20,
ARGSPELLFLAG_40 = 0x40,
ARGSPELLFLAG_80 = 0x80
};
enum {
OPTSPELLFLAG_1 = 1,
OPTSPELLFLAG_2 = 2,
OPTSPELLFLAG_4 = 4,
OPTSPELLFLAG_8 = 8,
OPTSPELLFLAG_10 = 0x10,
OPTSPELLFLAG_20 = 0x20,
OPTSPELLFLAG_40 = 0x40,
OPTSPELLFLAG_80 = 0x80
};
static void Option_PushList(OptionList *lst) {
Args_Push(1, lst, 0);
}
static void Option_PushOpt(Option *opt, const char *optname) {
char *cpy;
short flags = ARGFLAG_2;
if (opt && (opt->avail & OTF_STICKY)) {
if (Utils_CompareOptionString(opt->names, optname, opt->avail & OTF_CASED, OTF_STICKY)) {
2022-10-07 19:02:27 +00:00
flags |= ARGFLAG_80;
}
}
cpy = xstrdup(optname);
Args_Push(flags, opt, cpy);
}
static void Option_PopOpt(char *optname) {
Opt48 *os = Args_Pop(ARGFLAG_2);
if (optname)
strcpy(optname, os->e.o.curopt);
free(os->e.o.curopt);
}
2023-01-11 22:29:53 +00:00
static void Option_PopList(void) {
2022-10-07 19:02:27 +00:00
Args_Pop(ARGFLAG_1);
}
2023-01-11 22:29:53 +00:00
void Args_InitStack(void) {
2022-10-07 19:02:27 +00:00
oStackPtr = 0;
}
2023-01-11 22:29:53 +00:00
int Args_StackSize(void) {
2022-10-07 19:02:27 +00:00
return oStackPtr;
}
void Args_Push(short flags, void *first, void *second) {
#line 104
OPTION_ASSERT(oStackPtr<MAXSTACK);
if (oStackPtr > 0)
{
short prev =
(flags & ARGFLAG_1) ? ARGFLAG_2 :
(flags & ARGFLAG_2) ? ARGFLAG_1 :
(flags & ARGFLAG_4) ? ARGFLAG_2 : -1;
OPTION_ASSERT(oStack[oStackPtr-1].flags & prev);
}
oStack[oStackPtr].e.v.first = first;
oStack[oStackPtr].e.v.second = second;
oStack[oStackPtr].flags = flags;
oStackPtr++;
}
Opt48 *Args_Pop(short flags)
{
OPTION_ASSERT(oStackPtr>0);
--oStackPtr;
OPTION_ASSERT(oStack[oStackPtr].flags & flags);
return &oStack[oStackPtr];
}
void Args_SpellStack(char *buffer, short flags) {
char *bptr;
Opt48 *os;
int sp;
int level;
bptr = buffer;
sp = 0;
level = 0;
os = &oStack[sp];
while (sp < oStackPtr) {
if (!flags || !(os->flags & ARGFLAG_20)) {
if (os->flags & ARGFLAG_4) {
Opt48 *po = os - 1;
if (!(os[-1].flags & ARGFLAG_40)) {
if ((level == 1 || level == 2) && !(po->flags & ARGFLAG_80))
*(bptr++) = (flags & ARGSPELLFLAG_20) ? '\n' : ' ';
os[-1].flags |= ARGFLAG_40;
} else if (level == 2) {
*(bptr++) = ',';
} else if (level == 3) {
*(bptr++) = '=';
}
strcpy(bptr, os->e.param);
bptr += strlen(bptr);
} else if (os->flags & ARGFLAG_2) {
if (level == 1) {
*(bptr++) = MAINOPTCHAR[0];
} else if (level == 2) {
Opt48 *po = os - 2;
if (!(os[-1].flags & ARGFLAG_40) && !(po->flags & ARGFLAG_80))
*(bptr++) = (flags & ARGSPELLFLAG_20) ? '\n' : ' ';
}
if (os[-1].flags & ARGFLAG_40) {
if (level == 2) {
if (flags & ARGSPELLFLAG_20)
*(bptr++) = ',';
else
*(bptr++) = ' ';
}
} else {
if (level == 3) {
*(bptr++) = '=';
}
}
os[-1].flags |= ARGFLAG_40;
strcpy(bptr, os->e.o.curopt);
bptr += strlen(bptr);
}
if (flags & ARGSPELLFLAG_20)
os->flags |= ARGFLAG_20;
}
if (os->flags & ARGFLAG_1)
level++;
++sp;
++os;
}
}
void Args_AddToToolArgs(anon0_50 *ta) {
char buffer[4096];
char *nptr;
Args_SpellStack(buffer, ARGSPELLFLAG_20);
nptr = strchr(buffer, '\n');
if (nptr) {
*(nptr++) = 0;
Arg_AddToToolArgs(ta, 2, buffer);
Arg_AddToToolArgs(ta, 1, 0);
} else {
nptr = buffer;
}
Arg_AddToToolArgs(ta, 2, nptr);
}
2023-01-11 22:29:53 +00:00
void Options_Init(void) {
2022-10-07 19:02:27 +00:00
numoptionlists = 0;
maxlegalset = 0;
numlegalset = 0;
numinternalset = 0;
if (legalset.list)
free(legalset.list);
if (internalset.list)
free(internalset.list);
legalset.list = 0;
legalset.flags =
((Option_ThisTool() & OTF_TOOL_COMPILER) ? LISTFLAGS_COMPILER : 0) |
((Option_ThisTool() & OTF_TOOL_LINKER) ? LISTFLAGS_LINKER : 0) |
((Option_ThisTool() & OTF_TOOL_DISASSEMBLER) ? LISTFLAGS_DISASSEMBLER : 0);
internalset.list = 0;
internalset.flags =
((Option_ThisTool() & OTF_TOOL_COMPILER) ? LISTFLAGS_COMPILER : 0) |
((Option_ThisTool() & OTF_TOOL_LINKER) ? LISTFLAGS_LINKER : 0) |
((Option_ThisTool() & OTF_TOOL_DISASSEMBLER) ? LISTFLAGS_DISASSEMBLER : 0);
Args_InitStack();
}
2023-01-11 22:29:53 +00:00
OptionList *Options_GetOptions(void) {
2022-10-07 19:02:27 +00:00
return &legalset;
}
2023-01-11 22:29:53 +00:00
void Options_SortOptions(void) {
2022-10-07 19:02:27 +00:00
int r;
if (numinternalset > 0) {
legalset.list = (Option **) xrealloc("options", legalset.list, sizeof(Option *) * (numinternalset + 1));
for (r = 0; r < numinternalset; r++) {
if (internalset.list[r]->avail & (OTF_STICKY | OTF_CASED))
2022-10-07 19:02:27 +00:00
legalset.list[numlegalset++] = internalset.list[r];
}
for (r = 0; r < numinternalset; r++) {
if (!(internalset.list[r]->avail & (OTF_STICKY | OTF_CASED)))
2022-10-07 19:02:27 +00:00
legalset.list[numlegalset++] = internalset.list[r];
}
legalset.list[numlegalset] = 0;
if (internalset.list)
free(internalset.list);
internalset.list = 0;
numinternalset = 0;
}
}
static void Options_AddOption(Option *opt) {
if (numinternalset >= maxlegalset) {
maxlegalset += 32;
internalset.list = (Option **) xrealloc("options", internalset.list, sizeof(Option *) * (maxlegalset + 1));
}
internalset.list[numinternalset++] = opt;
internalset.list[numinternalset] = 0;
}
int Options_AddList(OptionList *optlst) {
Option **ptr;
if (numoptionlists >= 32)
CLPFatalError("Too many option lists defined!");
optionlists[numoptionlists++] = optlst;
for (ptr = optlst->list; *ptr; ptr++)
Options_AddOption(*ptr);
return 1;
}
int Options_AddLists(OptionList **optlst) {
int ret = 1;
OptionList **ptr;
for (ptr = optlst; *ptr; ptr++) {
ret = Options_AddList(*ptr);
if (!ret)
return ret;
}
return ret;
}
static void Options_Reset(OptionList *optlst) {
Option **os;
os = optlst->list;
if (os) {
for (; *os; os++) {
(*os)->avail &= ~(OTF_INTERNAL_ALREADY_SEEN | OTF_INTERNAL_SEEN_CONFLICTED);
2022-10-07 19:02:27 +00:00
}
}
}
static void Option_SpellList(char *buffer, OptionList *conflicts, int flags) {
Option **scan;
Boolean first;
int total;
char tmp[256];
Option **next;
int slflags;
2022-10-07 19:02:27 +00:00
scan = conflicts->list;
first = 1;
total = 0;
while (*scan) {
next = scan + 1;
if (!((*scan)->avail & (((parseopts.helpFlags & HELPFLAGS_SECRET) ? 0 : OTF_SECRET) | ((parseopts.helpFlags & HELPFLAGS_DEPRECATED) ? 0 : OTF_DEPRECATED) | OTF_SUBSTITUTED)) && (*scan)->names[0]) {
if (!first)
buffer += sprintf(buffer, ", ");
if (first)
first = 0;
if (total > 1) {
while (*next && (((*next)->avail & (((parseopts.helpFlags & HELPFLAGS_SECRET) ? 0 : OTF_SECRET) | ((parseopts.helpFlags & HELPFLAGS_DEPRECATED) ? 0 : OTF_DEPRECATED) | OTF_SUBSTITUTED)) || !(*next)->names[0])) {
++next;
}
if (!*next)
buffer += sprintf(buffer, "or ");
}
slflags = (flags & OPTSPELLFLAG_2) ? SLFLAGS_2 : SLFLAGS_1;
switch ((*scan)->avail & OTF_SLFLAGS_MASK) {
case OTF_SLFLAGS_8:
slflags |= SLFLAGS_8;
break;
case OTF_SLFLAGS_20:
slflags |= SLFLAGS_20;
break;
case OTF_SLFLAGS_10:
slflags |= SLFLAGS_10;
break;
}
Utils_SpellList((*scan)->names, tmp, slflags);
total++;
buffer += sprintf(buffer, "%s", tmp);
if ((*scan)->avail & OTF_HAS_SUB_OPTIONS)
2022-10-07 19:02:27 +00:00
buffer += sprintf(buffer, " ...");
}
scan++;
}
}
int Option_ForTool(Option *opt, int which) {
return !which || (opt->avail & which);
}
2023-01-11 22:29:53 +00:00
int Option_ThisTool(void) {
2022-10-07 19:02:27 +00:00
return (pTool->TYPE == CWDROPINCOMPILERTYPE) ? OTF_TOOL_COMPILER : OTF_TOOL_LINKER;
}
int Option_ForThisTool(Option *opt) {
return !Option_ForTool(opt, OTF_TOOL_MASK) || Option_ForTool(opt, Option_ThisTool());
}
int Option_AlsoPassedToTool(Option *opt, int which) {
return Option_ForThisTool(opt) && Option_ForTool(opt, which);
}
int Option_AlsoPassedFromThisTool(Option *opt) {
return Option_ForThisTool(opt) && Option_ForTool(opt, ~Option_ThisTool() & OTF_TOOL_MASK);
}
static Boolean Option_ContinuesThisLevel(int level, ArgToken *tok) {
ArgToken *tmp;
2022-10-07 19:02:27 +00:00
int ret; // not in stabs but i think this exists
if (level == 1) {
return (tok->val == ATK_ARG_END) || (tok->val == ATK_OPTION) || (tok->val == ATK_ARG);
2022-10-07 19:02:27 +00:00
} else if (level == 2) {
tmp = Arg_UsedToken();
ret = (tok->val == ATK_COMMA && tmp->val != ATK_OPTION) || (tok->val == ATK_ARG && tmp->val != ATK_ARG_END);
2022-10-07 19:02:27 +00:00
Arg_UndoToken();
return ret;
} else if (level == 3) {
return (tok->val == ATK_EQUALS) || (tok->val == ATK_ARG);
2022-10-07 19:02:27 +00:00
} else {
return 0;
}
}
static short endingStack[5][3];
static Boolean Option_IsEndingThisLevel(int level, ArgToken *tok) {
ArgToken *tmp;
2022-10-07 19:02:27 +00:00
if (!tok)
return 1;
if (tok->val == endingStack[level][0])
return 1;
if (endingStack[level][1] && tok->val == endingStack[level][1]) {
tmp = Arg_UsedToken();
if (tmp && tmp->val == endingStack[level][2]) {
Arg_UndoToken();
return 1;
}
Arg_UndoToken();
}
return 0;
2022-10-07 19:02:27 +00:00
}
static Boolean Option_IsEndingLevel(int level, ArgToken *tok) {
if (!tok)
return 1;
while (level > 0) {
if (Option_IsEndingThisLevel(level - 1, tok))
return 1;
level--;
}
return 0;
2022-10-07 19:02:27 +00:00
}
int Option_Parse(Option *opt, int oflags) {
int ret;
int pushed;
int samelevel;
int subparse;
int flags;
char errstr[1024];
Option **cscan;
Option **scan;
int goingtosubparse;
ArgToken *tok;
ret = 1;
pushed = 0;
samelevel = (opt->avail & OTF_GLOBAL) == (oflags & OFLAGS_1);
subparse = (oflags & OFLAGS_2) != 0;
flags = 0;
if (subparse) flags |= PFLAGS_4;
if (oflags & OFLAGS_8) flags |= PFLAGS_8;
if (oflags & OFLAGS_40) flags |= PFLAGS_1;
if (curopt[0]) {
pushed = 1;
Option_PushOpt(opt, curopt);
}
if (samelevel) {
if (!(flags & PFLAGS_1)) {
if ((opt->avail & OTF_INTERNAL_ALREADY_SEEN) && (opt->avail & OTF_ONLY_ONCE)) {
Option_Warning(CLPStr30_OptionShouldNotBeSpecifiedMultipleTimes);
} else if (opt->avail & OTF_HAS_CONFLICTS) {
cscan = opt->conflicts->list;
while (*cscan && (*cscan == opt || !((*cscan)->avail & OTF_INTERNAL_ALREADY_SEEN))) {
++cscan;
}
if (*cscan && *cscan != opt) {
(*cscan)->avail &= ~OTF_INTERNAL_ALREADY_SEEN;
Option_SpellList(errstr, opt->conflicts, oflags);
if (opt->conflicts->help)
Option_Warning(CLPStr32_OptionOverridesEffectWithHelp, (*cscan)->names, errstr, opt->conflicts->help);
else
Option_Warning(CLPStr31_OptionOverridesEffect, (*cscan)->names, errstr);
}
}
}
if (Option_ThisTool() == OTF_TOOL_COMPILER && Option_ForTool(opt, OTF_TOOL_LINKER | OTF_TOOL_DISASSEMBLER)) {
flags |= PFLAGS_2;
if (!Option_ForThisTool(opt))
flags |= PFLAGS_1;
if (!subparse)
Arg_AddToToolArgs(&linkargs, ATK_ARG_END, 0);
Args_AddToToolArgs(&linkargs);
}
if (!(flags & PFLAGS_1)) {
if (opt->avail & OTF_OBSOLETE) {
if (opt->help)
Option_Error(CLPStr22_OptionObsoleteWithHelp, opt->help);
else
Option_Error(CLPStr21_OptionObsolete);
flags |= PFLAGS_1;
}
if (opt->avail & OTF_IGNORED) {
if (!(opt->avail & (OTF_WARNING | OTF_MEANINGLESS))) {
if (opt->help)
Option_Warning(CLPStr27_OptionIgnoredWithText, opt->help);
else
Option_Warning(CLPStr26_OptionIgnored);
}
flags |= PFLAGS_1;
} else if (opt->avail & OTF_SUBSTITUTED) {
Option_Warning(CLPStr23_OptionXSubstitutedWithX, curopt, opt->help);
} else if (opt->avail & OTF_DEPRECATED) {
if (opt->help)
Option_Warning(CLPStr25_OptionDeprecatedWithHelp, opt->help);
else
Option_Warning(CLPStr24_OptionDeprecated);
}
if (opt->avail & OTF_WARNING)
Option_Warning(CLPStr28_WarningText, opt->help);
if (opt->avail & OTF_MEANINGLESS)
Option_Warning(CLPStr29_OptionHasNoEffect);
}
opt->avail |= OTF_INTERNAL_ALREADY_SEEN;
if (opt->avail & OTF_HAS_CONFLICTS) {
scan = opt->conflicts->list;
opt->avail |= OTF_INTERNAL_SEEN_CONFLICTED;
while (*scan) {
(*scan)->avail |= OTF_INTERNAL_SEEN_CONFLICTED;
scan++;
}
}
} else {
flags |= PFLAGS_1;
}
goingtosubparse = opt->avail & OTF_HAS_SUB_OPTIONS;
if (opt->param) {
ret = Params_Parse(opt->param, flags | (goingtosubparse ? PFLAGS_20 : 0));
} else {
tok = Arg_PeekToken();
if (tok && tok->val == ATK_EQUALS)
Arg_UsedToken();
}
if (ret && goingtosubparse) {
ret = ret && Options_Parse(
opt->sub,
(oflags & ~OFLAGS_4)
| OFLAGS_2
| ((flags & PFLAGS_1) ? OFLAGS_40 : 0)
| (subparse ? OFLAGS_10 : 0)
| ((opt->avail & OTF_SUB_OPTIONS_OPTIONAL) ? OFLAGS_4 : 0)
);
}
if (pushed)
Option_PopOpt(curopt);
if (Option_ThisTool() == OTF_TOOL_COMPILER && !subparse)
Arg_AddToToolArgs(&linkargs, ATK_ARG_END, 0);
return ret;
2022-10-07 19:02:27 +00:00
}
static int Option_MatchString(char *list, char *str, int flags, int *result) {
int str_len;
char cpy[64];
if (result)
*result = 0;
if (!list[0] && !str[0])
return 1;
while (*list) {
if (Utils_CompareOptionString(list, str, flags & OTF_CASED, 0))
return 1;
switch (flags & OTF_SLFLAGS_MASK) {
case OTF_SLFLAGS_8:
if (my_tolower(str[0]) == 'n' && my_tolower(str[1]) == 'o' && Utils_CompareOptionString(list, str + 2, flags & OTF_CASED, 0)) {
if (result)
*result |= 0x100000;
return 1;
}
break;
case OTF_SLFLAGS_20:
if (my_tolower(str[0]) == 'n' && my_tolower(str[1]) == 'o' && str[2] == '-' && Utils_CompareOptionString(list, str + 3, flags & OTF_CASED, 0)) {
if (result)
*result |= 0x400000;
return 1;
}
break;
case OTF_SLFLAGS_10:
str_len = strlen(str);
if (str[str_len - 1] == '-') {
strcpy(cpy, str);
cpy[str_len - 1] = 0;
if (Utils_CompareOptionString(list, cpy, flags & OTF_CASED, 0)) {
if (result)
*result |= 0x200000;
return 1;
}
}
break;
}
while (*list && *list != '|')
++list;
if (*list)
++list;
if (*list == '|')
++list;
}
return 0;
2022-10-07 19:02:27 +00:00
}
static Option *Option_Lookup(OptionList *search, int unk, int *flags) {
Option **os;
Option *stickyopt;
int stickyflags;
Boolean matched;
char *names;
os = search->list;
stickyopt = 0;
stickyflags = *flags;
if (os) {
while (*os) {
names = (*os)->names;
if (((*os)->avail & OTF_STICKY) == OTF_STICKY) {
while (*names && *names != '|')
++names;
if (*names)
++names;
if (*names == '|')
++names;
}
matched = Option_MatchString(names, curopt, (*os)->avail & (OTF_SLFLAGS_MASK | OTF_CASED), flags) && (*names || names == (*os)->names);
if (matched) {
if (!stickyopt || (*os)->names[0] == curopt[0] || strlen(curopt) > 1)
return *os;
}
if ((*os)->avail & OTF_STICKY) {
matched = Utils_CompareOptionString((*os)->names, curopt, (*os)->avail & OTF_CASED, 2);
if (matched)
stickyflags |= OTF_STICKY;
} else {
matched = 0;
}
if (matched)
stickyopt = *os;
++os;
}
}
*flags = stickyflags;
return stickyopt;
2022-10-07 19:02:27 +00:00
}
static int Options_DoParse(OptionList *search, int flags) {
// search: r26 *n
// flags: r28 *n
int haderrors; // r30 *n
int parsedany; // r23 *n
int failed; // r24 *n
int matchflags; // stack 0x38
int subparse; // r20 *n
ArgToken *starttok; // r0 (actually r19 i think?)
int mystery_r31; // figure out what var this actually is
ArgToken *tok; // r25 *n
ArgToken *opttok; // r27 *n
ArgToken *token_r18; // r18 MAYBE????
Option *opt; // r16 *n
2022-10-07 19:02:27 +00:00
Boolean isOpt; // r0
char *lptr; // r17 *n
char *optname; // r16 *n
// 915
haderrors = 0;
// 917
failed = 0;
// 918
matchflags = 0;
// 920
subparse = (flags & OFLAGS_2) != 0;
// 921
mystery_r31 = subparse && (flags & OFLAGS_10);
// 925
opttok = 0;
// 929
mystery_r31 = (subparse == 0) ? 1 : (mystery_r31 == 0) ? 2 : 3;
starttok = Arg_PeekToken(); // i think this is starttok
while ((token_r18 = Arg_PeekToken())) {
parsedany = 0;
isOpt = ((mystery_r31 == 1) && (token_r18->val == ATK_OPTION)) || ((mystery_r31 == 2) && (token_r18->val == ATK_ARG) && (token_r18->text[0] || search->flags & LISTFLAGS_4)) || ((mystery_r31 == 3) && (token_r18->val == ATK_EQUALS));
// 950 17CFD4
if ((mystery_r31 == 3) && isOpt) {
token_r18 = Arg_UsedToken();
isOpt = token_r18 && (token_r18->val == ATK_ARG);
flags &= ~OFLAGS_4;
}
// 957 17D00C
if (isOpt) {
// 959
opt = 0;
// 960
Arg_GetTokenText(token_r18, curopt, sizeof(curopt), 0);
// 963
if (curopt[0]) {
opt = Option_Lookup(search, 0x700000, &matchflags);
if (opt) {
opttok = token_r18;
if (!(matchflags & 2)) {
// 972
if (token_r18->val == ATK_OPTION)
Arg_UsedToken();
token_r18 = Arg_UsedToken();
} else {
lptr = opt->names;
optname = token_r18->text;
while (*lptr && *lptr != '|')
++lptr;
token_r18 = Arg_UsedToken();
if (!subparse)
strcpy(token_r18->text, optname + (lptr - opt->names));
curopt[(lptr - opt->names)] = 0;
if (!token_r18->text || !token_r18->text[0]) {
Option_PushOpt(0, curopt);
Option_ParamError(CLPStr34_ArgumentsExpected, curopt);
Option_PopOpt(0);
return 0;
}
}
}
}
// 1006
if (!opt) {
// 1009
if (search->flags & LISTFLAGS_4) {
char saveopt[1024]; // stack 0xBC
strcpy(saveopt, curopt);
curopt[0] = 0;
opt = Option_Lookup(search, 0, &matchflags);
strcpy(curopt, token_r18->text);
// 1019
if (opt) {
if (opt->names[0])
token_r18 = Arg_UsedToken();
if (token_r18->val == ATK_EQUALS)
Arg_UsedToken();
haderrors = Option_Parse(opt, flags) == 0;
parsedany = 1;
if (haderrors)
failed = 1;
opt = 0;
} else {
CLPFatalError("Missing default for variable list");
return 0;
}
// 1041
strcpy(curopt, saveopt);
} else if (!opt) {
// 1059
curopt[0] = 0;
// 1061
if (mystery_r31 > 1) {
if ((flags & OFLAGS_4) && token_r18 == starttok)
return haderrors == 0;
// 1072
if (search->flags & LISTFLAGS_ALLOW_UNKNOWNS) {
if (!(flags & OFLAGS_1)) {
Option_SpellList(curparam, search, flags);
Option_Warning(CLPStr20_UnknownOptionX_ExpectedOneOfX, token_r18->text, curparam);
}
Arg_UsedToken();
parsedany = 1;
} else {
// 1090
Option_SpellList(curparam, search, flags);
Option_Error(CLPStr20_UnknownOptionX_ExpectedOneOfX, token_r18->text, curparam);
failed = 1;
haderrors++;
}
} else {
// 1099
if ((search->flags & LISTFLAGS_ALLOW_UNKNOWNS) || parseopts.ignoreUnknown) {
// 1101
if (!(flags & OFLAGS_1))
Option_Warning(CLPStr19_UnknownOptionX, token_r18->text);
Arg_UsedToken();
Arg_GetToken();
parsedany = 1;
} else {
// 1115
Option_Error(CLPStr19_UnknownOptionX, token_r18->text);
failed = 1;
haderrors++;
}
}
}
}
// 1126 - after_if_1006
if (!haderrors && !failed && opt) {
flags &= ~OFLAGS_8;
if (matchflags & 0x700000)
flags |= OFLAGS_8;
haderrors = Option_Parse(opt, flags) == 0;
if (haderrors)
failed = 1;
parsedany++;
} // else: goto 1229
} else if ((mystery_r31 == 1) && (token_r18->val == ATK_ARG)) {
// 1142
opttok = 0;
curopt[0] = 0;
opt = Option_Lookup(search, 0, &matchflags);
strcpy(curopt, token_r18->text);
if (!opt) {
Option_Warning(CLPStr33_NoDefaultHandlerSetUpForX_Ignoring, curopt);
failed = 1;
} else {
if (!(flags & OFLAGS_1)) {
haderrors = Option_Parse(opt, flags) == 0;
} else {
parseopts.possibleFiles++;
haderrors = 0;
}
2023-01-11 22:29:53 +00:00
parsedany++;
if (haderrors)
failed = 1;
else
Arg_UsedToken();
}
} else if ((mystery_r31 > 1) && Option_IsEndingLevel(mystery_r31, token_r18)) {
// 1193
Option *opt;
char saveopt[64]; // stack 0x7C
strcpy(saveopt, curopt);
if (!(search->flags & LISTFLAGS_4)) {
curopt[0] = 0;
opt = Option_Lookup(search, 0, &matchflags); // probably wrong result reg
} else {
opt = 0; // probably wrong reg
}
// 1203
if (!opt) {
// 1205
if (!(flags & OFLAGS_4)) {
Option_Error(CLPStr34_ArgumentsExpected, saveopt);
failed = 1;
haderrors++;
} else {
strcpy(curopt, saveopt);
break;
}
} else {
// 1219
haderrors = Option_Parse(opt, flags) == 0;
parsedany = 1;
if (haderrors)
failed = 1;
}
// 1224
strcpy(curopt, saveopt);
}
// 1229 after_if_1126
// This is where tok comes into play.
tok = Arg_PeekToken();
// 1231
if (!failed) {
if (tok && (tok->val == ATK_ARG) && (matchflags & 2)) {
// 1235
ArgToken *prev; // r16
char sticky[64]; // stack 0x3C
prev = Arg_UndoToken();
tok = Arg_UsedToken();
if (tok->text[0] && prev == opttok) {
if (opttok) {
strcpy(sticky, opttok->text);
sticky[strlen(tok->text)] = 0;
Option_PushOpt(0, sticky);
Param_Error(CLPStr36_UnexpectedAdditionalArgumentX, Arg_GetTokenName(tok));
Option_PopOpt(0);
} else {
CLPReportError(CLPStr36_UnexpectedAdditionalArgumentX, Arg_GetTokenName(tok));
}
// 1251
haderrors++;
// goes to 1323
} else {
// 1256
if (!tok->text[0])
tok = Arg_UsedToken();
// 1257
if (flags & OFLAGS_1)
parseopts.possibleFiles++;
// goes to 1323
}
} else {
// 1267
if (Option_IsEndingThisLevel(mystery_r31 - 1, tok))
break;
if (Option_IsEndingThisLevel(mystery_r31 + 1, tok)) {
// 1276
ArgToken *prev = tok; // r16
tok = Arg_UsedToken();
// 1278
if ((mystery_r31 != 1) || (tok->val != ATK_OPTION)) {
// 1280
if (opttok) {
Option_PushOpt(0, opttok->text);
if (tok->val == ATK_ARG)
Param_Error(CLPStr36_UnexpectedAdditionalArgumentX, Arg_GetTokenName(tok));
else
Param_Error(CLPStr35_TokenXNotExpected, Arg_GetTokenName(prev));
Option_PopOpt(opttok->text);
} else if (tok->val == ATK_ARG) {
// 1292
CLPReportError(CLPStr36_UnexpectedAdditionalArgumentX, Arg_GetTokenName(tok));
} else {
// 1294
CLPReportError(CLPStr35_TokenXNotExpected, Arg_GetTokenName(prev));
}
haderrors++;
failed++;
}
// goto 1323
} else if ((mystery_r31 < 2) && Option_IsEndingThisLevel(mystery_r31 + 2, tok)) {
// 1303
if (opttok) {
Option_PushOpt(0, opttok->text);
if (tok->val == ATK_ARG)
Param_Error(CLPStr36_UnexpectedAdditionalArgumentX, Arg_GetTokenName(tok));
else
Param_Error(CLPStr35_TokenXNotExpected, Arg_GetTokenName(tok));
Option_PopOpt(opttok->text);
} else if (tok->val == ATK_ARG) {
CLPReportError(CLPStr36_UnexpectedAdditionalArgumentX, Arg_GetTokenName(tok));
} else {
CLPReportError(CLPStr35_TokenXNotExpected, Arg_GetTokenName(tok));
}
haderrors++;
failed++;
}
}
} // else: 1323
if (haderrors || failed) {
while (!Option_IsEndingLevel(mystery_r31, tok))
tok = Arg_GetToken();
if (!tok)
tok = Arg_UndoToken();
#line 1335
OPTION_ASSERT(tok);
}
if (!parsedany || haderrors)
break;
if (Option_IsEndingThisLevel(mystery_r31, tok))
Arg_UsedToken();
else if (!Option_ContinuesThisLevel(mystery_r31, tok))
break;
}
return haderrors == 0;
2022-10-07 19:02:27 +00:00
}
int Options_Parse(OptionList *options, int flags) {
// options: r30
// flags: r31
int ret; // r31
char savecuropt[64]; // stack 0x3C
Options_Reset(options);
Option_PushList(options);
if (!(flags & 2)) {
ret = Options_DoParse(options, flags);
if (Option_ThisTool() == OTF_TOOL_COMPILER)
Arg_AddToToolArgs(&linkargs, 1, 0);
} else {
strcpy(savecuropt, curopt);
ret = Options_DoParse(options, flags);
strcpy(curopt, savecuropt);
}
Option_PopList();
return ret;
}
int Option_ParseDefaultOption(OptionList *options) {
// options: r31
int ret; // r31
Option *dopt; // r0
int matchflags; // 0x3C
Options_Reset(options);
Option_PushList(options);
strcpy(curopt, "defaultoptions");
dopt = Option_Lookup(options, 0, &matchflags);
if (!dopt) {
CLPFatalError("Default options not defined");
ret = 1;
} else {
ret = Option_Parse(dopt, 0);
}
Option_PopList();
return ret;
}
void Option_ParamError(short id, va_list ap) {
char buf[4096];
CLPGetErrorString(id, buf);
sprintf(&buf[strlen(buf)], "\nwhile parsing option '");
Args_SpellStack(&buf[strlen(buf)], 0);
sprintf(&buf[strlen(buf)], "'");
CLPReportError_V(buf, ap);
}
void Option_ParamWarning(short id, va_list ap) {
char buf[1024];
CLPGetErrorString(id, buf);
sprintf(&buf[strlen(buf)], "\nwhile parsing option '");
Args_SpellStack(&buf[strlen(buf)], 0);
sprintf(&buf[strlen(buf)], "'");
CLPReportWarning_V(buf, ap);
}
void Option_OptionError(short id, va_list ap) {
char buf[1024];
CLPGetErrorString(id, buf);
if (Args_StackSize() >= 2) {
sprintf(&buf[strlen(buf)], "\nwhile parsing option '");
Args_SpellStack(&buf[strlen(buf)], 0);
sprintf(&buf[strlen(buf)], "'");
}
CLPReportError_V(buf, ap);
}
void Option_OptionWarning(short id, va_list ap) {
char buf[1024];
CLPGetErrorString(id, buf);
if (Args_StackSize() >= 2) {
sprintf(&buf[strlen(buf)], "\nwhile parsing option '");
Args_SpellStack(&buf[strlen(buf)], 0);
sprintf(&buf[strlen(buf)], "'");
}
CLPReportWarning_V(buf, ap);
}
void Option_Error(short id, ...) {
va_list va;
va_start(va, id);
Option_OptionError(id, va);
va_end(va);
}
void Option_Warning(short id, ...) {
va_list va;
va_start(va, id);
Option_OptionWarning(id, va);
va_end(va);
}
int Options_Help(const char *keyword) {
// keyword: r31
int scan; // r26
OptionList *lst; // r25
Help_Init();
if (parseopts.helpFlags & HELPFLAGS_USAGE) {
ShowVersion(1);
Help_Line('=');
Help_Usage();
} else {
ShowVersion(1);
for (scan = 0; scan < numoptionlists; scan++) {
if ((lst = optionlists[scan])) {
if (parseopts.helpFlags & HELPFLAGS_8000) {
if (keyword && keyword[0] && lst->help && strstr(lst->help, keyword))
Help_Options(lst, 0, "");
} else {
Help_Options(lst, 0, keyword);
}
}
}
}
Help_Term();
return 1;
}
int Option_Help(const char *opt) {
// opt: r31
Option *find; // r29
int matchflags; // stack 0x3C
int ret; // r29
find = 0;
Option_PushList(Options_GetOptions());
Option_PushOpt(0, "help");
if (opt[0] == MAINOPTCHAR[0])
strcpy(curopt, opt + 1);
else
strcpy(curopt, opt);
if (!curopt[1])
find = Option_Lookup(Options_GetOptions(), 0x700002, &matchflags);
if (!find)
find = Option_Lookup(Options_GetOptions(), 0x700000, &matchflags);
if (find) {
Help_Init();
if (!Help_Option(Options_GetOptions(), find, 0, ""))
CLPReportWarning(CLPStr38_NoHelpAvailableForOptionX, opt);
2022-10-07 19:02:27 +00:00
Help_Term();
ret = 1;
} else {
Option_Error(CLPStr19_UnknownOptionX, opt);
2022-10-07 19:02:27 +00:00
ret = 0;
}
Option_PopOpt(curopt);
Option_PopList();
return ret;
}
2023-01-11 22:29:53 +00:00
int Options_DisplayHelp(void) {
2022-10-07 19:02:27 +00:00
if (parseopts.helpFlags & HELPFLAGS_1)
return Option_Help(parseopts.helpKey);
2022-10-07 19:02:27 +00:00
else
return Options_Help(parseopts.helpKey);
2022-10-07 19:02:27 +00:00
}