#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(void) { Args_Pop(ARGFLAG_1); } void Args_InitStack(void) { oStackPtr = 0; } int Args_StackSize(void) { return oStackPtr; } void Args_Push(short flags, void *first, void *second) { OS_ASSERT(104, 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(void) { 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(void) { return &legalset; } void Options_SortOptions(void) { 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(void) { 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++; 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(); OS_ASSERT(1335, 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(void) { if (parseopts.helpFlags & HELPFLAGS_1) return Option_Help(parseopts.helpKey); else return Options_Help(parseopts.helpKey); }