summaryrefslogtreecommitdiff
path: root/unsorted/Option.c
diff options
context:
space:
mode:
authorAsh Wolf <ninji@wuffs.org>2022-10-19 21:16:13 +0100
committerAsh Wolf <ninji@wuffs.org>2022-10-19 21:16:13 +0100
commitd1f153d34b023d81768f6087f67dbfff714bafc9 (patch)
treea694d470a60655d0cda15a70791fbdb90a2398cf /unsorted/Option.c
parent775b6861666af36d317fb577cf489e2c6377f878 (diff)
downloadMWCC-d1f153d34b023d81768f6087f67dbfff714bafc9.tar.gz
MWCC-d1f153d34b023d81768f6087f67dbfff714bafc9.zip
let's commit all this before my VM blows up and nukes my work
Diffstat (limited to 'unsorted/Option.c')
-rw-r--r--unsorted/Option.c1134
1 files changed, 1134 insertions, 0 deletions
diff --git a/unsorted/Option.c b/unsorted/Option.c
new file mode 100644
index 0000000..410c807
--- /dev/null
+++ b/unsorted/Option.c
@@ -0,0 +1,1134 @@
+#include "parser.h"
+
+#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;
+
+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)) {
+ 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);
+}
+
+static void Option_PopList() {
+ Args_Pop(ARGFLAG_1);
+}
+
+void Args_InitStack() {
+ oStackPtr = 0;
+}
+int Args_StackSize() {
+ 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);
+}
+
+void Options_Init() {
+ 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();
+}
+
+OptionList *Options_GetOptions() {
+ return &legalset;
+}
+
+void Options_SortOptions() {
+ 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))
+ legalset.list[numlegalset++] = internalset.list[r];
+ }
+ for (r = 0; r < numinternalset; r++) {
+ if (!(internalset.list[r]->avail & (OTF_STICKY | OTF_CASED)))
+ 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);
+ }
+ }
+}
+
+static void Option_SpellList(char *buffer, OptionList *conflicts, int flags) {
+ Option **scan;
+ Boolean first;
+ int total;
+ char tmp[256];
+ Option **next;
+ int slflags;
+
+ 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)
+ buffer += sprintf(buffer, " ...");
+ }
+ scan++;
+ }
+}
+
+int Option_ForTool(Option *opt, int which) {
+ return !which || (opt->avail & which);
+}
+
+int Option_ThisTool() {
+ 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;
+ 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);
+ } 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);
+ Arg_UndoToken();
+ return ret;
+ } else if (level == 3) {
+ return (tok->val == ATK_EQUALS) || (tok->val == ATK_ARG);
+ } else {
+ return 0;
+ }
+}
+
+static short endingStack[5][3];
+static Boolean Option_IsEndingThisLevel(int level, ArgToken *tok) {
+ ArgToken *tmp;
+
+ 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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
+
+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
+ 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;
+ }
+ parsedany = 1;
+ 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;
+}
+
+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);
+ Help_Term();
+ ret = 1;
+ } else {
+ Option_Error(CLPStr19_UnknownOptionX, opt);
+ ret = 0;
+ }
+
+ Option_PopOpt(curopt);
+ Option_PopList();
+ return ret;
+}
+
+int Options_DisplayHelp() {
+ if (parseopts.helpFlags & HELPFLAGS_1)
+ return Option_Help(parseopts.helpKey);
+ else
+ return Options_Help(parseopts.helpKey);
+}