summaryrefslogtreecommitdiff
path: root/Option.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--Option.c655
1 files changed, 592 insertions, 63 deletions
diff --git a/Option.c b/Option.c
index 4a09705..1ff5209 100644
--- a/Option.c
+++ b/Option.c
@@ -15,6 +15,8 @@ static OptionList internalset;
int numoptionlists;
static OptionList *optionlists[32];
+extern char curparam[1024]; // check me
+
enum {
ARGFLAG_1 = 1,
ARGFLAG_2 = 2,
@@ -288,16 +290,12 @@ static void Options_Reset(OptionList *optlst) {
}
static void Option_SpellList(char *buffer, OptionList *conflicts, int flags) {
- // r25: buffer
- // r0: conflicts
- // r26: flags
-
- Option **scan; // r30
- Boolean first; // r29
- int total; // r28
- char tmp[256]; // stack 0x58
- Option **next; // r27
- int slflags; // r6
+ Option **scan;
+ Boolean first;
+ int total;
+ char tmp[256];
+ Option **next;
+ int slflags;
scan = conflicts->list;
first = 1;
@@ -305,7 +303,6 @@ static void Option_SpellList(char *buffer, OptionList *conflicts, int flags) {
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]) {
- // 17C1BC
if (!first)
buffer += sprintf(buffer, ", ");
if (first)
@@ -365,8 +362,7 @@ int Option_AlsoPassedFromThisTool(Option *opt) {
}
static Boolean Option_ContinuesThisLevel(int level, ArgToken *tok) {
- // tok: r30
- ArgToken *tmp; // r0
+ ArgToken *tmp;
int ret; // not in stabs but i think this exists
if (level == 1) {
@@ -385,74 +381,607 @@ static Boolean Option_ContinuesThisLevel(int level, ArgToken *tok) {
static short endingStack[5][3];
static Boolean Option_IsEndingThisLevel(int level, ArgToken *tok) {
- // level, tok: r0
- ArgToken *tmp; // r0
+ ArgToken *tmp;
if (!tok)
- return 0;
- // todo
+ 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) {
- // level: r30
- // tok: r31
+ if (!tok)
+ return 1;
+
+ while (level > 0) {
+ if (Option_IsEndingThisLevel(level - 1, tok))
+ return 1;
+ level--;
+ }
+
+ return 0;
}
+enum {
+ OFLAGS_1 = 1,
+ OFLAGS_2 = 2,
+ OFLAGS_4 = 4,
+ OFLAGS_8 = 8,
+ OFLAGS_10 = 0x10,
+ OFLAGS_20 = 0x20,
+ OFLAGS_40 = 0x40,
+ OFLAGS_80 = 0x80
+};
+enum {
+ PFLAGS_1 = 1,
+ PFLAGS_2 = 2,
+ PFLAGS_4 = 4,
+ PFLAGS_8 = 8,
+ PFLAGS_10 = 0x10,
+ PFLAGS_20 = 0x20,
+ PFLAGS_40 = 0x40,
+ PFLAGS_80 = 0x80
+};
+
int Option_Parse(Option *opt, int oflags) {
- // opt: r24
- // oflags: r25
- int ret; // r29
- int pushed; // r28
- int samelevel; // r30
- int subparse; // r27
- int flags; // r26
- char errstr[1024]; // stack 0x3C
- Option **cscan; // r30
- Option **scan; // r5
- int goingtosubparse; // r30
- ArgToken *tok; // r0
+ 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 & OTF80000000) && (opt->avail & OTF20000)) {
+ Option_Warning(30);
+ } else if (opt->avail & OTF40000) {
+ cscan = opt->conflicts->list;
+ while (*cscan && (*cscan == opt || !((*cscan)->avail & OTF80000000))) {
+ ++cscan;
+ }
+
+ if (*cscan && *cscan != opt) {
+ (*cscan)->avail &= ~OTF80000000;
+ Option_SpellList(errstr, opt->conflicts, oflags);
+ if (opt->conflicts->help)
+ Option_Warning(32, (*cscan)->names, errstr, opt->conflicts->help);
+ else
+ Option_Warning(31, (*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_1, 0);
+ Args_AddToToolArgs(&linkargs);
+ }
+
+ if (!(flags & PFLAGS_1)) {
+ if (opt->avail & OTF_OBSOLETE) {
+ if (opt->help)
+ Option_Error(22, opt->help);
+ else
+ Option_Error(21);
+ flags |= PFLAGS_1;
+ }
+
+ if (opt->avail & OTF_IGNORED) {
+ if (!(opt->avail & (OTF_WARNING | OTF_MEANINGLESS))) {
+ if (opt->help)
+ Option_Warning(27, opt->help);
+ else
+ Option_Warning(26);
+ }
+ flags |= PFLAGS_1;
+ } else if (opt->avail & OTF_SUBSTITUTED) {
+ Option_Warning(23, curopt, opt->help);
+ } else if (opt->avail & OTF_DEPRECATED) {
+ if (opt->help)
+ Option_Warning(25, opt->help);
+ else
+ Option_Warning(24);
+ }
+
+ if (opt->avail & OTF_WARNING)
+ Option_Warning(28, opt->help);
+ if (opt->avail & OTF_MEANINGLESS)
+ Option_Warning(29);
+ }
+
+ opt->avail |= OTF80000000;
+ if (opt->avail & OTF40000) {
+ scan = opt->conflicts->list;
+ opt->avail |= OTF40000000;
+ while (*scan) {
+ (*scan)->avail |= OTF40000000;
+ scan++;
+ }
+ }
+ } else {
+ flags |= PFLAGS_1;
+ }
+
+ goingtosubparse = opt->avail & OTF8000;
+ if (opt->param) {
+ ret = Params_Parse(opt->param, flags | (goingtosubparse ? PFLAGS_20 : 0));
+ } else {
+ tok = Arg_PeekToken();
+ if (tok && tok->val == ATK_4)
+ 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 & OTF10000) ? OFLAGS_4 : 0)
+ );
+ }
+
+ if (pushed)
+ Option_PopOpt(curopt);
+
+ if (Option_ThisTool() == OTF_TOOL_COMPILER && !subparse)
+ Arg_AddToToolArgs(&linkargs, ATK_1, 0);
+
+ return ret;
}
static int Option_MatchString(char *list, char *str, int flags, int *result) {
- // list: r26
- // str: r27
- // flags: r0
- // result: r28
- int str_len; // r0
- char cpy[64]; // stack 0x3C
+ 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) {
- // search: r0
- // flags: r25
- Option **os; // r29
- Option *stickyopt; // r28
- int stickyflags; // r27
- Boolean matched; // r0
- char *names; // r26
+ 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 & OTF2) == OTF2) {
+ 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 & OTF2) {
+ matched = Utils_CompareOptionString((*os)->names, curopt, (*os)->avail & OTF_CASED, 2);
+ if (matched)
+ stickyflags |= OTF2;
+ } else {
+ matched = 0;
+ }
+
+ if (matched)
+ stickyopt = *os;
+
+ ++os;
+ }
+ }
+
+ *flags = stickyflags;
+ return stickyopt;
}
static int Options_DoParse(OptionList *search, int flags) {
- // search: r26
- // flags: r28
- int haderrors; // r30
- int parsedany; // r23
- int failed; // r24
- int matchflags; // stack 0x3C
- int subparse; // r20
- ArgToken *starttok; // r0
- ArgToken *tok; // r25
- ArgToken *opttok; // r27
- Option *opt; // r16
+ // 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
- char *optname; // r16
- char saveopt[1024]; // stack 0xBC
- // Option *opt; // r3
- // char saveopt[64]; // stack 0x7C
- // ArgToken *prev; // r0
- // char sticky[64]; // stack 0x3C
- // ArgToken *prev; // r16
+ 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_3)) || ((mystery_r31 == 2) && (token_r18->val == ATK_2) && (token_r18->text[0] || search->flags & LISTFLAGS_4)) || ((mystery_r31 == 3) && (token_r18->val == ATK_4));
+ // 950 17CFD4
+ if ((mystery_r31 == 3) && isOpt) {
+ token_r18 = Arg_UsedToken();
+ isOpt = token_r18 && (token_r18->val == ATK_2);
+ 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_3)
+ 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(34, 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_4)
+ 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_2) {
+ if (!(flags & OFLAGS_1)) {
+ Option_SpellList(curparam, search, flags);
+ Option_Warning(20, token_r18->text, curparam);
+ }
+ Arg_UsedToken();
+ parsedany = 1;
+ } else {
+ // 1090
+ Option_SpellList(curparam, search, flags);
+ Option_Error(20, token_r18->text, curparam);
+ failed = 1;
+ haderrors++;
+ }
+ } else {
+ // 1099
+ if ((search->flags & LISTFLAGS_2) || parseopts.ignoreUnknown) {
+ // 1101
+ if (!(flags & OFLAGS_1))
+ Option_Warning(19, token_r18->text);
+ Arg_UsedToken();
+ Arg_GetToken();
+ parsedany = 1;
+ } else {
+ // 1115
+ Option_Error(19, 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_2)) {
+ // 1142
+ opttok = 0;
+ curopt[0] = 0;
+ opt = Option_Lookup(search, 0, &matchflags);
+ strcpy(curopt, token_r18->text);
+ if (!opt) {
+ Option_Warning(33, 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(34, 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_2) && (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(36, Arg_GetTokenName(tok));
+ Option_PopOpt(0);
+ } else {
+ CLPReportError(36, 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_3)) {
+ // 1280
+ if (opttok) {
+ Option_PushOpt(0, opttok->text);
+ if (tok->val == ATK_2)
+ Param_Error(36, Arg_GetTokenName(tok));
+ else
+ Param_Error(35, Arg_GetTokenName(prev));
+ Option_PopOpt(opttok->text);
+ } else if (tok->val == ATK_2) {
+ // 1292
+ CLPReportError(36, Arg_GetTokenName(tok));
+ } else {
+ // 1294
+ CLPReportError(35, 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_2)
+ Param_Error(36, Arg_GetTokenName(tok));
+ else
+ Param_Error(35, Arg_GetTokenName(tok));
+ Option_PopOpt(opttok->text);
+ } else if (tok->val == ATK_2) {
+ CLPReportError(36, Arg_GetTokenName(tok));
+ } else {
+ CLPReportError(35, 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) {