diff options
Diffstat (limited to '')
-rw-r--r-- | Help.c | 564 |
1 files changed, 564 insertions, 0 deletions
@@ -0,0 +1,564 @@ +#include "mwcc_decomp.h" +typedef struct _Side { + short offset; + short width; + char buffer[1024]; + short bptr; + short blen; + short indent; + short vrow; + short vcol; + unsigned char atEOL; + unsigned char impInd; +} Side; + +short helpExtras; +unsigned char showedHelp; +Side left; +Side right; +Side all; +char **helptext; +static char outLine[256]; + +static void Help_Output(Side *left, Side *right); +static void Help_OutputSingle(Side *all); +static void Help_Flush(); + +static void Side_Init(Side *s, short offset, short width) { + memset(s, 0, sizeof(Side)); + s->offset = offset; + s->width = width; +} + +static void Side_Print(Side *s, const char *format, ...) { + char c; + char *text; + char buffer[1024]; + va_list args; + + va_start(args, format); + vsprintf(buffer, format, args); + va_end(args); + + text = buffer; + while (*text) { + if (s->blen < 1024) { + c = *(text++); + if (c == '~' && *text == '~') { + c = *MAINOPTCHAR; + text++; + } + + s->buffer[(s->bptr + s->blen) & 1023] = c; + s->blen++; + } else { + if (s == &left) + Help_Output(&left, &right); + else + Help_OutputSingle(&all); + } + } +} + +static void Side_NewLine(Side *s) { + Side_Print(s, "\n"); +} + +static void Side_Indent(Side *s, short how) { + if ((s->width - s->indent - how) > (parseopts.ioCols / 8)) + s->indent += how; + else if ((s->width - s->indent - 1) > (parseopts.ioCols / 10)) + s->indent++; +} + +static void Side_Outdent(Side *s, short how) { + if ((s->width - s->indent) < (parseopts.ioCols / 8)) + s->indent++; + else if (s->indent >= how) + s->indent -= how; +} + +static unsigned char isBreaker(char c) { + return (c == 10) || (c == 13) || (c == 32) || (c == 9) || (c == 8) || (c == '|'); +} + +static void Side_DumpLine(Side *s) { + short col; + short len; + short afterspace; + short eol; + short ind; + char c; + + eol = 0; + ind = 0; + col = s->offset + s->indent; + s->vcol = s->indent; + len = 0; + afterspace = s->width - s->indent; + + while (s->blen > 0 && s->vcol < s->width && !eol && !ind) { + c = s->buffer[s->bptr]; + outLine[col + len] = c; + s->vcol++; + len++; + + if (isBreaker(c)) { + afterspace = len; + eol = (c == '\n') || (c == '\r'); + eol += (c == '\r'); + ind = (c == '\b') || (c == '\t'); + ind += (c == '\b'); + } + + s->bptr = (s->bptr + 1) & 1023; + s->blen--; + } + + if (s->blen || eol || ind) { + s->blen += len - afterspace; + s->bptr = (s->bptr - (len - afterspace)) & 1023; + if (eol || ind) { + len++; + afterspace--; + } + + while (len > afterspace) { + outLine[col + --len] = ' '; + } + } + + s->vcol = 0; + s->vrow++; + s->atEOL = (eol == 1) || ind || !s->blen; + if ((s->atEOL || ind) && s->impInd) { + Side_Outdent(s, parseopts.ioCols / 40); + s->impInd = 0; + } + if (ind) { + if (ind == 1) + Side_Indent(s, parseopts.ioCols / 25); + else + Side_Outdent(s, parseopts.ioCols / 25); + } else if (!s->atEOL && s != &all && !s->impInd) { + Side_Indent(s, parseopts.ioCols / 40); + s->impInd = 1; + } +} + +static void Help_PrintLine() { + HPrintF(helptext, "%.*s\n", parseopts.ioCols - 1, outLine); +} + +static void Help_Output(Side *left, Side *right) { + while (left->blen || right->blen) { + memset(outLine, ' ', parseopts.ioCols); + outLine[left->offset + left->width + 1] = '#'; + if (left->atEOL && right->atEOL) + left->atEOL = right->atEOL = 0; + if (!left->atEOL) + Side_DumpLine(left); + if (!right->atEOL) + Side_DumpLine(right); + Help_PrintLine(); + } +} + +static void Help_OutputSingle(Side *all) { + while (all->blen) { + memset(outLine, ' ', parseopts.ioCols); + if (all->atEOL) + all->atEOL = 0; + if (!all->atEOL) + Side_DumpLine(all); + Help_PrintLine(); + } +} + +static void Help_Flush() { + Help_Output(&left, &right); +} + +static void Help_NewLine() { + Side_NewLine(&left); + Side_NewLine(&right); +} + +int Help_Option(struct OptionList *lst, struct Option *opt, int subprint, const char *keyword) { + char pfbuf[512]; + char slflags; + int listFlags; + Boolean allNoArgs; + PARAM_T *lastparam; + Boolean print; + Boolean printMe; + + if (!opt->names[0] && !(lst->flags & LISTFLAGS_4)) + return 0; + + if (keyword && keyword[0] && !strstr(opt->names, keyword) && (!opt->help || !strstr(opt->help, keyword))) + return 0; + + if ((opt->avail & OTF_SECRET) && !(parseopts.helpFlags & HELPFLAGS_SECRET)) + return 0; + + if ((opt->avail & OTF_OBSOLETE) && !(parseopts.helpFlags & HELPFLAGS_OBSOLETE)) + return 0; + + if ((opt->avail & OTF_DEPRECATED) && !(parseopts.helpFlags & HELPFLAGS_DEPRECATED)) + return 0; + + if ((opt->avail & OTF_IGNORED) && !(parseopts.helpFlags & HELPFLAGS_IGNORED)) + return 0; + + if ((opt->avail & OTF_MEANINGLESS) && !(parseopts.helpFlags & HELPFLAGS_MEANINGLESS)) + return 0; + + if (!(parseopts.helpFlags & HELPFLAGS_NORMAL) && !(opt->avail & OTF_ALL_HIDDEN_BY_DEFAULT)) + return 0; + + if (opt->help || (opt->avail & OTF8000)) { + allNoArgs = 1; + lastparam = 0; + if (parseopts.helpFlags & HELPFLAGS_SPACES) + Help_NewLine(); + if ((opt->avail & OTF_GLOBAL) && !subprint) + Side_Print(&right, "global; "); + if (compat != 1 && (opt->avail & OTF_CASED)) + Side_Print(&right, "cased; "); + + slflags = (subprint == 0) ? SLFLAGS_1 : SLFLAGS_2; + switch (opt->avail & OTF_SLFLAGS_MASK) { + case OTF_SLFLAGS_8: + slflags = slflags | SLFLAGS_8; + break; + case OTF_SLFLAGS_10: + slflags = slflags | SLFLAGS_10; + break; + case OTF_SLFLAGS_20: + slflags = slflags | SLFLAGS_20; + break; + } + if (opt->avail & OTF2) + slflags = slflags | SLFLAGS_40; + + Utils_SpellList(opt->names[0] ? opt->names : "...", pfbuf, slflags); + Side_Print(&left, pfbuf); + + if (opt->avail & OTF_OBSOLETE) + Side_Print(&right, "obsolete;\r"); + if (opt->avail & OTF_COMPATIBILITY) + Side_Print(&right, "compatibility;\r"); + if (opt->avail & OTF_IGNORED) + Side_Print(&right, "ignored;\r"); + + listFlags = ((lst->flags & LISTFLAGS_COMPILER) ? OTF_TOOL_COMPILER : 0) | ((lst->flags & LISTFLAGS_LINKER) ? OTF_TOOL_LINKER : 0) | ((lst->flags & LISTFLAGS_DISASSEMBLER) ? OTF_TOOL_DISASSEMBLER : 0); + if (!Option_ForThisTool(opt) || Option_AlsoPassedFromThisTool(opt) || listFlags != Option_ThisTool()) { + print = 0; + printMe = 1; + if ((opt->avail & OTF_TOOL_MASK) != (unsigned int) listFlags) + print = 1; + if (Option_ForThisTool(opt) && Option_AlsoPassedFromThisTool(opt)) + printMe = 0; + + if (print) { + char opttool[64] = ""; // stack 0x44 + if ((opt->avail & OTF_TOOL_MASK) == (unsigned int) OTF_TOOL_MASK) { + strcat(opttool, "all tools"); + } else { + if (Option_ForTool(opt, OTF_TOOL_COMPILER) && ((Option_ThisTool() != (unsigned int) OTF_TOOL_COMPILER) || printMe)) { + strcat(opttool, "this tool"); + } + if (Option_ForTool(opt, OTF_TOOL_LINKER) && ((Option_ThisTool() != (unsigned int) OTF_TOOL_LINKER) || printMe)) { + if (opttool[0]) + strcat(opttool, ", "); + strcat(opttool, "linker"); + } + if (Option_ForTool(opt, OTF_TOOL_DISASSEMBLER) && ((Option_ThisTool() != (unsigned int) OTF_TOOL_DISASSEMBLER) || printMe)) { + if (opttool[0]) + strcat(opttool, ", "); + strcat(opttool, "disassembler"); + } + if (!Option_ForTool(opt, OTF_TOOL_MASK)) + strcat(opttool, "another tool"); + } + + if (printMe || !Option_ForThisTool(opt)) { + Side_Print(&right, "for %s;\r", opttool); + } else if (parseopts.passingArgs) { + Side_Print(&right, "passed to %s;\r", opttool); + } + } + } + + if (opt->avail & OTF_WARNING) + Side_Print(&right, "warning:\r"); + + if (opt->avail & OTF_DEPRECATED) + Side_Print(&right, "deprecated;\rinstead use "); + else if (opt->avail & OTF_SUBSTITUTED) + Side_Print(&right, "substituted with "); + + if (opt->help) + Side_Print(&right, "%s", opt->help); + + if (opt->param && !(opt->avail & OTF_IGNORED)) { + PARAM_T *scan = opt->param; + PARAM_T *firstparam = 0; + const char *desc; + const char *help; + const char *defaul; + while (scan) { + if ((scan->flags & PARAMFLAGS_3) != PARAMFLAGS_1) { + if (!firstparam) + firstparam = scan; + + allNoArgs = 0; + Param_DescHelp(scan, &desc, &help, &defaul); + if (desc) { + if (((scan->flags & PARAMFLAGS_3) == PARAMFLAGS_2) && scan->which != PARAMWHICH_Setting && scan->which != PARAMWHICH_IfArg) { + if (SEPOPTSTR[0] == ' ') { + Side_Print(&left, (scan != firstparam) ? "[," : subprint ? "[=" : " ["); + } else { + Side_Print(&left, "[%s", (scan != firstparam) ? "," : subprint ? "=" : SEPOPTSTR); + } + } else { + Side_Print(&left, (scan != firstparam) ? "," : subprint ? "=" : ((opt->avail & OTF2) && !strchr(opt->names, '|')) ? "" : SEPOPTSTR); + } + Side_Print(&left, "%s", desc); + if (((scan->flags & PARAMFLAGS_3) == PARAMFLAGS_2) && scan->which != PARAMWHICH_Setting && scan->which != PARAMWHICH_IfArg) { + Side_Print(&left, "]"); + } + if (help) { + if ((scan->flags & PARAMFLAGS_3) != PARAMFLAGS_2) + Side_Print(&right, "; for '%s', %s", desc, help); + else + Side_Print(&right, "; if parameter specified, %s", help); + } + if (defaul && !(opt->avail & OTF2000)) { + if (firstparam == scan) + Side_Print(&right, "; default is %s", defaul); + else + Side_Print(&right, ",%s", defaul); + } + } + } + lastparam = scan; + scan = scan->next; + } + + if (allNoArgs && !(opt->avail & OTF2000)) { + PARAM_T *scan = opt->param; + Boolean isdefault = scan ? 1 : 0; + while (scan && isdefault) { + isdefault &= Param_Compare(scan); + scan = scan->next; + } + + if (isdefault) + Side_Print(&right, "; default"); + } + } + + if (opt->avail & OTF_MEANINGLESS) + Side_Print(&right, "; meaningless for this target"); + + if ((opt->avail & OTF8000) && opt->sub) { + if (!allNoArgs) { + Side_Print( + &left, + "%s", + (opt->avail & OTF10000) ? ((lastparam->flags & PARAMFLAGS_8) ? "[=" : "[,") : ((lastparam->flags & PARAMFLAGS_8) ? "," : "=") + ); + } else if (!(opt->avail & OTF2)) { + if (opt->avail & OTF10000) { + if (SEPOPTSTR[0] == ' ') + Side_Print(&left, subprint ? "[=" : " ["); + else + Side_Print(&left, "[%s", subprint ? "=" : SEPOPTSTR); + } else { + Side_Print(&left, "%c", subprint ? '=' : SEPOPTSTR[0]); + } + } else { + if (opt->avail & OTF10000) { + Side_Print(&left, subprint ? "[" : (SEPOPTSTR[0] == ' ') ? " [" : "["); + } + } + + Side_Print( + &left, + "%s%s%s", + opt->sub->help ? opt->sub->help : "keyword", + (opt->sub->flags & PARAMFLAGS_1) ? "" : "[,...]", + (opt->avail & OTF10000) ? "]" : "" + ); + + Side_Print(&left, "\t"); + Side_Print(&right, "\t"); + Help_Options(opt->sub, 1, ""); + Side_Print(&left, "\b"); + Side_Print(&right, "\b"); + } else { + Side_Print(&left, "\n"); + Side_Print(&right, "\n"); + } + } + + Help_Flush(); + return 1; +} + +inline int IsCompiler() { + return (Option_ThisTool() == (unsigned int) OTF_TOOL_COMPILER) ? LISTFLAGS_COMPILER : LISTFLAGS_LINKER; +} + +void Help_Options(struct OptionList *lst, int subprint, const char *keyword) { + Option **opts; + int toolflags; + Boolean show; + + opts = lst->list; + toolflags = 0; + if (Option_ThisTool() == (unsigned int) OTF_TOOL_COMPILER) { + toolflags |= LISTFLAGS_COMPILER; + } else { + toolflags |= LISTFLAGS_LINKER; + } + + // review me maybe? + if (!subprint && (parseopts.helpFlags & HELPFLAGS_TOOL)) { + if ((parseopts.helpFlags & HELPFLAGS_TOOL_BOTH) == HELPFLAGS_TOOL_THIS && (lst->flags & LISTFLAGS_TOOL_MASK) && !(lst->flags & toolflags)) + return; + if ((parseopts.helpFlags & HELPFLAGS_TOOL_BOTH) == HELPFLAGS_TOOL_OTHER && (((lst->flags & LISTFLAGS_TOOL_MASK) == (unsigned int) toolflags) || ((lst->flags & LISTFLAGS_TOOL_MASK) == (unsigned int) LISTFLAGS_NONE))) + return; + } + + if (lst->help && !subprint && opts[0]) { + Help_Line('-'); + Side_Print(&all, "%s", lst->help); + Help_OutputSingle(&all); + Help_Line('-'); + } + + while (*opts) { + show = 0; + if (!(parseopts.helpFlags & HELPFLAGS_TOOL)) { + if (((parseopts.helpFlags & HELPFLAGS_TOOL_BOTH) == HELPFLAGS_TOOL_BOTH) && (parseopts.passingArgs ? (Option_ForTool(*opts, OTF_TOOL_LINKER) || Option_ForTool(*opts, OTF_TOOL_DISASSEMBLER)) : 1) && Option_ForThisTool(*opts)) + show = 1; + } else if ((parseopts.helpFlags & HELPFLAGS_TOOL_BOTH) == HELPFLAGS_TOOL_BOTH) { + show = 1; + } else if ((parseopts.helpFlags & HELPFLAGS_TOOL_THIS) && Option_ForThisTool(*opts)) { + show = 1; + } else if ((parseopts.helpFlags & HELPFLAGS_TOOL_OTHER) && !Option_ForThisTool(*opts)) { + show = 1; + } else if ((parseopts.helpFlags & HELPFLAGS_TOOL_OTHER) && Option_ForTool(*opts, ~Option_ThisTool() & OTF_TOOL_MASK)) { + show = 1; + } + + if (show) + Help_Option(lst, *opts, subprint, keyword); + + ++opts; + } + + if (subprint && (parseopts.helpFlags & HELPFLAGS_SPACES)) + Help_NewLine(); + Help_Flush(); + if (!subprint) + HPrintF(helptext, "\n"); +} + +void Help_Usage() { + Side_Print( + &all, + "\tGuide to help:\b" + "\tWhen an option is specified as '~~xxx | yy[y] | zzz', then either '~~xxx', '~~yy', '~~yyy', or '~~zzz' matches the option.\b" + "\tAn option given as '~~[no]xxx' may be given as '~~xxx' or '~~noxxx'; '~~noxxx' reverses the meaning of the option.\b" + ); + Help_OutputSingle(&all); + + Side_Print( + &all, + "\tFor most options, the option and the parameters are separated by a %sspace. When the option's name is '~~xxx+', however, the parameter must directly follow the option, without the '+' (as in '~~xxx45').\b", + (compat != 1) ? "" : "colon or " + ); + Side_Print( + &all, + "\tA parameter included in brackets '[]' is optional. An ellipsis '...' indicates that the previous type of parameter may be repeated as a list.\b" + ); + Help_OutputSingle(&all); + + Side_Print( + &all, + "\t%s-- \"compatability\" indicates that the option is borrowed from another vendor's tool and may only approximate its counterpart.\r" + "-- \"global\" indicates that the option has an effect over the entire command line and is parsed before any other options. When several global options are specified, they are interpreted in order.\r" + "-- \"deprecated\" indicates that the option will be eliminated in the future and should not be used any longer. An alternative form is supplied.\r", + (compat != 1) ? "-- \"cased\" indicates that the option is case-sensitive. By default, no options are case-sensitive.\r" : ""); + Help_OutputSingle(&all); + + Side_Print( + &all, + "-- \"ignored\" means the option will be accepted but has no effect on the tool.\r" + "-- \"meaningless\" means the option is accepted but probably has no meaning for the target OS.\r" + "-- \"obsolete\" means the option was once deprecated and is now gone.\r" + "-- \"substituted\" means the option has the same effect as another. This points out a preferred form and prevents confusion when similar options appear in the help.\r" + "-- \"default\" in the help text indicates that the given value or variation of an option will be used unless otherwise overridden. \b" + ); + Help_OutputSingle(&all); + + Side_Print( + &all, + "\tThe symbols ',' %s separate options and parameters unconditionally; to include one of these symbols in a parameter or filename, escape it (e.g., as '\\,' in mwcc file.c\\,v).\b\n", + (compat != 1) ? "and '='" : ", ':', and '='" + ); + Help_OutputSingle(&all); + + if (parseopts.passingArgs && pTool->TYPE == CWDROPINCOMPILERTYPE) + Side_Print( + &all, + "\tThis tool calls the linker (unless a compiler option such as ~~c prevents it) and understands linker options -- use '~~help tool=other' to see them. Options marked \"passed to linker\" are used by the compiler and the linker; options marked \"for linker\" are used only by the linker. When using the compiler and linker separately, you must pass the common options to both.\b\n" + ); + Help_OutputSingle(&all); +} + +void Help_Null() { + Side_Print(&all, + "%s [options, filenames...]\n\nExecute '%s %shelp' for more information.", + OS_GetFileNamePtr(parseopts.args->argv[0]), + OS_GetFileNamePtr(parseopts.args->argv[0]), + MAINOPTCHAR + ); + Help_OutputSingle(&all); +} + +void Help_Init() { + short lb; + short le; + short rb; + short re; + + if (!(helptext = NewHandle(0))) { + fprintf(stderr, "\n*** Out of memory\n"); + exit(-23); + } + + lb = parseopts.ioCols / 40; + le = (parseopts.ioCols / 3) + lb; + rb = le + 3 + ((parseopts.ioCols / 60) & ~1); + re = parseopts.ioCols - 1; + Side_Init(&left, lb, le - lb); + Side_Init(&right, rb, re - rb); + Side_Init(&all, 0, re); +} + +void Help_Line(char ch) { + char line[256]; + memset(line, ch, 255); + line[255] = 0; + HPrintF(helptext, "%.*s\n", parseopts.ioCols - 1, line); +} + +void Help_Term() { + ShowTextHandle(0, helptext); + DisposeHandle(helptext); +} |