From 97f6a2438df1eaeb4128ce36f29346ea38a3db4a Mon Sep 17 00:00:00 2001 From: Ash Wolf Date: Fri, 7 Oct 2022 20:02:27 +0100 Subject: first very unfinished commit lol --- Option.c | 630 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 630 insertions(+) create mode 100644 Option.c (limited to 'Option.c') diff --git a/Option.c b/Option.c new file mode 100644 index 0000000..4a09705 --- /dev/null +++ b/Option.c @@ -0,0 +1,630 @@ +#include "mwcc_decomp.h" + +#define OPTION_ASSERT(cond) do { if (!(cond)) { printf("%s:%u: failed assertion\n", __FILE__, __LINE__); abort(); } } while(0) + +#define MAXSTACK 8 + +int oStackPtr; +Opt48 oStack[8]; +char curopt[1024]; +int maxlegalset; +int numlegalset; +int numinternalset; +static OptionList legalset; +static OptionList internalset; +int numoptionlists; +static OptionList *optionlists[32]; + +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 & OTF2)) { + if (Utils_CompareOptionString(opt->names, optname, opt->avail & OTF_CASED, OTF2)) { + 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 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 & (OTF2 | OTF_CASED)) + legalset.list[numlegalset++] = internalset.list[r]; + } + for (r = 0; r < numinternalset; r++) { + if (!(internalset.list[r]->avail & (OTF2 | 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 &= ~(OTF80000000 | OTF40000000); + } + } +} + +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 + + 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]) { + // 17C1BC + 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 & OTF8000) + 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) { + // tok: r30 + ArgToken *tmp; // r0 + int ret; // not in stabs but i think this exists + + if (level == 1) { + return (tok->val == ATK_1) || (tok->val == ATK_3) || (tok->val == ATK_2); + } else if (level == 2) { + tmp = Arg_UsedToken(); + ret = (tok->val == ATK_5 && tmp->val != ATK_3) || (tok->val == ATK_2 && tmp->val != ATK_1); + Arg_UndoToken(); + return ret; + } else if (level == 3) { + return (tok->val == ATK_4) || (tok->val == ATK_2); + } else { + return 0; + } +} + +static short endingStack[5][3]; +static Boolean Option_IsEndingThisLevel(int level, ArgToken *tok) { + // level, tok: r0 + ArgToken *tmp; // r0 + + if (!tok) + return 0; + // todo +} + +static Boolean Option_IsEndingLevel(int level, ArgToken *tok) { + // level: r30 + // tok: r31 +} + +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 +} + +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 +} + +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 +} + +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 + 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 +} + +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(38, opt); + Help_Term(); + ret = 1; + } else { + Option_Error(19, opt); + ret = 0; + } + + Option_PopOpt(curopt); + Option_PopList(); + return ret; +} + +int Options_DisplayHelp() { + if (parseopts.helpFlags & HELPFLAGS_1) + Option_Help(parseopts.helpKey); + else + Options_Help(parseopts.helpKey); +} -- cgit v1.2.3