diff options
author | Ash Wolf <ninji@wuffs.org> | 2023-01-15 12:14:05 +0000 |
---|---|---|
committer | Ash Wolf <ninji@wuffs.org> | 2023-01-15 12:14:05 +0000 |
commit | 35d488e972a9dd75ce3867c000405f128b79c615 (patch) | |
tree | e3319a23d9aa0d4725f88a99fdd5131488a334a9 /command_line/C++_Parser/Src | |
parent | 8078e7f897aaae9b492b22475060052d68b9c547 (diff) | |
download | MWCC-35d488e972a9dd75ce3867c000405f128b79c615.tar.gz MWCC-35d488e972a9dd75ce3867c000405f128b79c615.zip |
reorganise things a bit to align further with the actual names/structure
Diffstat (limited to 'command_line/C++_Parser/Src')
17 files changed, 5704 insertions, 0 deletions
diff --git a/command_line/C++_Parser/Src/Library/Arguments.c b/command_line/C++_Parser/Src/Library/Arguments.c new file mode 100644 index 0000000..631f282 --- /dev/null +++ b/command_line/C++_Parser/Src/Library/Arguments.c @@ -0,0 +1,590 @@ +#include "parser.h" + +char compat; +char *MAINOPTCHAR; +char *FIRSTARGCHAR; +char *SEPOPTSTR; +char SEPOPTCHAR; +char SEP1; +char SEP2; +char SEP3; +char RESPFILECHAR; +char *RESPFILESTR; +static ArgToken *argtoks; +static int numargtoks; +static int maxargtoks; +unsigned char parserDebug; +static unsigned char in_response_file; +static int margc; +static int margind; +static char **margv; +static OSFileHandle respfilehandle; +static char *respfile; +static char *respfilestart; +static unsigned long respfilesize; +static int scantok; +anon0_50 linkargs; +anon0_50 prelinkargs; +anon0_50 postlinkargs; + +static void Arg_AddToken(short val, char *text); +static void Arg_Setup(int argc, char **argv); +static void Arg_SkipRespFileWS(); +static unsigned char Arg_OpenRespFile(const char *name); +static void Arg_CloseRespFile(); +static char *Arg_GetRespFileToken(); +static char *Arg_GetNext(unsigned char allow_resp); +static unsigned char Arg_GotMore(); +static void Arg_Parse(); +static void Arg_GrowArgs(anon0_50 *ta); +static void Arg_GrowArg(anon0_50 *ta, char *txt); + +static void Arg_AddToken(short val, char *text) { + ArgToken *cur; + ArgToken *prev; + ArgToken *pprev; + ArgToken *ppprev; + ArgToken *pppprev; + + if (numargtoks > 0) + prev = &argtoks[numargtoks - 1]; + else + prev = 0; + + if (prev && prev->val == ATK_ARG && prev->text[0] == 0) { + pppprev = ppprev = pprev = 0; + if (numargtoks > 3) + pppprev = &argtoks[numargtoks - 4]; + if (numargtoks > 2) + ppprev = &argtoks[numargtoks - 3]; + if (numargtoks > 1) + pprev = &argtoks[numargtoks - 2]; + + if (pprev) { + if ((int) val == ATK_ARG_END && (pprev->val == ATK_COMMA || pprev->val == ATK_EQUALS) && (ppprev->val != ATK_ARG || pppprev->val != ATK_OPTION)) { + if (parserDebug) + printf("Coalescing args with '%s'\n", Arg_GetTokenName(pprev)); + val = pprev->val; + numargtoks -= 2; + } else if (pprev->val == ATK_ARG_END && ((int) val == ATK_COMMA || (int) val == ATK_EQUALS)) { + if (parserDebug) + printf("Coalescing args, removing '%s'\n", Arg_GetTokenName(pprev)); + numargtoks -= 2; + } + } + } + + if (numargtoks >= maxargtoks) { + argtoks = (ArgToken *) xrealloc("argument list", argtoks, sizeof(ArgToken) * (maxargtoks + 16)); + maxargtoks += 16; + } + + cur = &argtoks[numargtoks]; + cur->val = val; + if (text) + cur->text = xstrdup(text); + else + cur->text = 0; + numargtoks++; +} + +static void Arg_Setup(int argc, char **argv) { + in_response_file = 0; + respfile = 0; + margc = argc; + margv = argv; + margind = 1; +} + +static void Arg_SkipRespFileWS(void) { +restart: + while (respfile[0] && isspace(respfile[0])) + ++respfile; + + if (respfile[0] == '\\' && respfile[1] == '#') { + ++respfile; + return; + } + + if (respfile[0] == '#') { + if ((respfile > respfilestart) ? (respfile[-1] != '\\') : 1) { + while (respfile[0] && respfile[0] != 10 && respfile[0] != 13) + ++respfile; + + while (respfile[0] == 13 || respfile[0] == 10) + ++respfile; + + goto restart; + } + } +} + +static unsigned char Arg_OpenRespFile(const char *name) { + struct OSSpec spec; + int err; + + if ( + (err = OS_MakeFileSpec(name, &spec)) + || (err = OS_NewFileHandle(&spec, 0, 0, &respfilehandle)) + || (err = OS_AppendHandle(&respfilehandle.hand, "", 1)) + || (err = OS_LockFileHandle(&respfilehandle, &respfile, &respfilesize)) + ) { + CLPOSAlert(CLPStr74, (short) err, "response ", name); + return 0; + } else { + respfilestart = respfile; + Arg_SkipRespFileWS(); + in_response_file = 1; + return 1; + } +} + +static void Arg_CloseRespFile(void) { + in_response_file = 0; + OS_FreeFileHandle(&respfilehandle); +} + +static char *Arg_GetRespFileToken(void) { + char *start; + char *ptr; + int quoting; + + quoting = 0; + if (respfile[0] == 0) + return 0; + + start = ptr = respfile; + while (respfile[0]) { + if (!quoting && isspace(respfile[0])) + break; + + if (respfile[0] == '"') { + quoting = !quoting; + respfile++; + } else if (respfile[0] == '\\' && respfile[1] == '"') { + *ptr = '"'; + respfile += 2; + ptr++; + } else { + *(ptr++) = *(respfile++); + } + } + + if (respfile[0]) + Arg_SkipRespFileWS(); + *ptr = 0; + return start; +} + +static char *Arg_GetNext(unsigned char allow_resp) { + char *ret; + int rfclen; + char *rfcequ; + +restart: + if (!in_response_file) { + rfclen = 1; + ret = margv[margind++]; + if (ret[0] == '\\' && ret[1] == RESPFILECHAR) { + ret++; + } else if (allow_resp) { + if (ret[0] == RESPFILECHAR || (RESPFILESTR[0] && !ustrncmp(ret, RESPFILESTR, rfclen = strlen(RESPFILESTR))) && ret[rfclen]) { + rfcequ = strchr(ret + rfclen, '='); + if (rfcequ) + rfclen = (rfcequ + 1) - ret; + if (Arg_OpenRespFile(ret + rfclen)) + goto restart; + ret = 0; + } + } + } else { + ret = Arg_GetRespFileToken(); + if (!ret) { + Arg_CloseRespFile(); + goto restart; + } + } + + if (parserDebug) + fprintf(stderr, "Got arg = '%s'\n", ret ? ret : "<NULL>"); + + return ret; +} + +static unsigned char Arg_GotMore(void) { + if (!in_response_file) + return margind < margc; + else if (respfile[0]) + return 1; + else + return margind < margc; +} + +static void Arg_Parse(void) { + unsigned char isOpt; + unsigned char isList; + char *arg; + char *argstart; + char buffer[4096]; + char *bufptr; + char ch; + + isOpt = 0; + isList = 0; + while (Arg_GotMore()) { + argstart = arg = Arg_GetNext(1); + if (!arg) + break; + + bufptr = buffer; + buffer[0] = 0; + isList = 0; + + if (arg[0] && arg[1] && strchr(MAINOPTCHAR, arg[0])) { + if (isOpt) + Arg_AddToken(ATK_ARG_END, 0); + buffer[0] = arg[1]; + buffer[1] = 0; + isOpt = 1; + isList = 0; + bufptr++; + arg += 2; + } else { + isOpt = 0; + } + + while (arg && arg[0]) { + ch = arg[0]; + if (arg[0] == '\\' && (arg[1] == SEP1 || arg[1] == SEP2 || arg[1] == SEP3)) { + ch = 0x80 | *(++arg); + } else if (compat == 1 && arg[0] == ':' && arg[1] == '\\') { + ch |= 0x80; + } + + if (ch != SEP1 && ch != SEP2 && ch != SEP3) { + if ((ch & 0x7F) == SEP1 || (ch & 0x7F) == SEP2 || (ch & 0x7F) == SEP3) + ch &= 0x7F; + *(bufptr++) = ch; + if (bufptr >= &buffer[sizeof(buffer)]) { + CLPReportError(CLPStr2, argstart, argstart + strlen(argstart) - 15, sizeof(buffer)); + } + *bufptr = 0; + } else { + if (isOpt) { + Arg_AddToken(ATK_OPTION, buffer); + Arg_AddToken(ATK_ARG, buffer); + } else { + Arg_AddToken(ATK_ARG, buffer); + } + + Arg_AddToken( + (unsigned char) ((ch == ',') ? ATK_COMMA : (((ch == '=') || (ch == SEP3)) ? ATK_EQUALS : ATK_END)), + 0 + ); + + bufptr = buffer; + buffer[0] = 0; + + if (ch == SEP1 || ch == SEP2 || ch == SEP3) + isOpt = 0; + isList = 1; + } + + arg++; + } + + // 1799C8 + if (isOpt && bufptr > &buffer[0]) { + Arg_AddToken(ATK_OPTION, buffer + (isList && strchr(MAINOPTCHAR, buffer[0]))); + Arg_AddToken(ATK_ARG, buffer + (isList && strchr(MAINOPTCHAR, buffer[0])) + 1); + } else { + Arg_AddToken(ATK_ARG, buffer); + Arg_AddToken(ATK_ARG_END, 0); + } + } + + if (isOpt || isList) + Arg_AddToken(ATK_ARG_END, 0); + Arg_AddToken(ATK_END, 0); +} + +enum { + COMPAT_0, + COMPAT_1, + COMPAT_2 +}; + +void Arg_Init(int theargc, char **theargv) { + int p; + int x; + + maxargtoks = 0; + numargtoks = 0; + parserDebug = 0; + if (theargc > 1 && !strcmp(theargv[1], "--parser-debug")) { + parserDebug = 1; + memmove(&theargv[1], &theargv[2], sizeof(char *) * (theargc - 1)); + theargc--; + } + + if ((int) compat == COMPAT_0) { + MAINOPTCHAR = "-"; + FIRSTARGCHAR = "="; + SEPOPTSTR = " "; + SEP1 = ','; + SEP2 = '='; + SEP3 = '='; + RESPFILECHAR = '@'; + RESPFILESTR = ""; + } else if ((int) compat == COMPAT_1) { + MAINOPTCHAR = "/-"; + FIRSTARGCHAR = ":"; + SEPOPTSTR = ":"; + SEP1 = ','; + SEP2 = '='; + SEP3 = ':'; + RESPFILECHAR = '@'; + RESPFILESTR = ""; + } else if ((int) compat == COMPAT_2) { + if (!MAINOPTCHAR) + MAINOPTCHAR = "-"; + if (!FIRSTARGCHAR) + FIRSTARGCHAR = "="; + if (!SEPOPTSTR) + SEPOPTSTR = " "; + if (!SEP1) + SEP1 = ','; + if (!SEP2) + SEP2 = '='; + if (!SEP3) + SEP3 = '='; + if (!RESPFILECHAR) + RESPFILECHAR = '@'; + if (!RESPFILESTR) + RESPFILESTR = ""; + } else { + CLPFatalError("Unknown parser compatibility type (%d)\n", (int) compat); + } + + if (parserDebug) { + printf("Incoming arguments: \n"); + for (p = 0; p < theargc; p++) { + printf("[%s] ", theargv[p]); + } + printf("\n"); + } + + Arg_Setup(theargc, theargv); + Arg_Parse(); + Arg_Reset(); + + if (parserDebug) { + for (x = 0; x < numargtoks; x++) { + printf("TOKEN: '%s'\n", Arg_GetTokenName(&argtoks[x])); + } + } +} + +void Arg_Terminate(void) { + ArgToken *cur; + + while (numargtoks > 0) { + cur = &argtoks[--numargtoks]; + if (cur->text) + free(cur->text); + } + + if (maxargtoks) + free(argtoks); + maxargtoks = 0; +} + +void Arg_Reset(void) { + scantok = 0; +} + +void Arg_Stop(ArgToken *where) { + ArgToken *cur; + + while (&argtoks[numargtoks] > where) { + cur = &argtoks[--numargtoks]; + if (cur->text) + free(cur->text); + cur->val = ATK_END; + cur->text = 0; + } + + argtoks[numargtoks++].val = ATK_ARG_END; + argtoks[numargtoks++].val = ATK_END; + scantok = numargtoks - 2; +} + +ArgToken *Arg_PeekToken(void) { + if (scantok >= numargtoks) + return 0; + else + return &argtoks[scantok]; +} + +ArgToken *Arg_UsedToken(void) { + if (scantok < numargtoks) + scantok++; + return Arg_PeekToken(); +} + +int Arg_IsEmpty(void) { + ArgToken *tok; + + tok = Arg_PeekToken(); + return (tok == 0 || tok->val == ATK_END); +} + +ArgToken *Arg_GetToken(void) { + ArgToken *ret; + + ret = Arg_PeekToken(); + if (ret) + scantok++; + return ret; +} + +ArgToken *Arg_UndoToken(void) { + if (scantok > 0) { + scantok--; + return Arg_PeekToken(); + } else { + return 0; + } +} + +const char *Arg_GetTokenName(ArgToken *tok) { + if ((int) tok->val == ATK_ARG) + return tok->text; + + return + ((int) tok->val == ATK_OPTION) ? "option" : + ((int) tok->val == ATK_COMMA) ? "comma" : + (((int) compat == COMPAT_1 && (int) tok->val == ATK_EQUALS)) ? "colon or equals" : + (((int) compat != COMPAT_1 && (int) tok->val == ATK_EQUALS)) ? "equals" : + ((int) tok->val == ATK_ARG_END) ? "end of argument" : + ((int) tok->val == ATK_END) ? "end of command line" : + "<error>"; +} + +const char *Arg_GetTokenText(ArgToken *tok, char *buffer, int maxlen, unsigned char warn) { + const char *ptr; + char *bptr; + int curlen; + + bptr = buffer; + curlen = 0; + if (tok->val == ATK_ARG || tok->val == ATK_OPTION) + ptr = tok->text; + else + ptr = Arg_GetTokenName(tok); + + while (*ptr && curlen++ < maxlen) { + *(bptr++) = *(ptr++); + } + + if (curlen < maxlen) { + bptr[0] = 0; + } else { + bptr[-1] = 0; + if (warn) + CLPReportWarning(CLPStr56, buffer, ptr + strlen(ptr) - ((maxlen <= 32) ? maxlen : 32), maxlen); + } + + return buffer; +} + +static void Arg_GrowArgs(anon0_50 *ta) { + int len; + + if (!ta->argv || (ta->argc + 1) >= ta->nargv) { + len = ta->nargv; + ta->nargv = len + 16; + ta->argv = xrealloc("argument list", ta->argv, sizeof(char *) * (ta->nargv + 1)); + while (len <= ta->nargv) { + ta->argv[len++] = 0; + } + } + + ta->argc++; +} + +static void Arg_GrowArg(anon0_50 *ta, char *txt) { + char **ptr; + int ptrlen; + + ptr = &ta->argv[ta->argc]; + + if (*ptr == 0) { + *ptr = xstrdup(txt); + } else { + ptrlen = strlen(*ptr); + *ptr = xrealloc("command line", *ptr, ptrlen + strlen(txt) + 1); + strcpy(*ptr + ptrlen, txt); + } +} + +void Arg_InitToolArgs(anon0_50 *ta) { + ta->argc = 0; + ta->nargv = 0; + ta->argv = 0; + Arg_GrowArgs(ta); +} + +void Arg_AddToToolArgs(anon0_50 *ta, short tokval, char *toktxt) { + switch (tokval) { + case ATK_END: + Arg_FinishToolArgs(ta); + break; + case ATK_ARG_END: + if (ta->argv && ta->argv[ta->argc]) + Arg_GrowArgs(ta); + break; + case ATK_ARG: + Arg_GrowArg(ta, toktxt); + break; + case ATK_OPTION: + Arg_GrowArg(ta, "-"); + break; + case ATK_EQUALS: + Arg_GrowArg(ta, "="); + break; + case ATK_COMMA: + Arg_GrowArg(ta, ","); + break; + default: + CLPFatalError(__FILE__, 787, "Unknown token (%d)", tokval); + break; + } +} + +void Arg_FinishToolArgs(anon0_50 *ta) { + Arg_GrowArgs(ta); + ta->argv[ta->argc] = 0; +} + +void Arg_ToolArgsForPlugin(anon0_50 *ta, struct CWCommandLineArgs *args) { + args->argc = 1; + args->argv = ta->argv; + + while (args->argv[args->argc]) + args->argc++; + + args->envp = 0; +} + +void Arg_FreeToolArgs(anon0_50 *ta) { + int x; + + if (ta->argv) { + for (x = 1; x < ta->argc; x++) { + if (ta->argv[x]) + free(ta->argv[x]); + } + free(ta->argv); + } +} diff --git a/command_line/C++_Parser/Src/Library/Help.c b/command_line/C++_Parser/Src/Library/Help.c new file mode 100644 index 0000000..74849a1 --- /dev/null +++ b/command_line/C++_Parser/Src/Library/Help.c @@ -0,0 +1,561 @@ +#include "parser.h" + +typedef struct _Side { + short offset; + short width; + char buffer[1024]; + short bptr; + short blen; + short indent; + short vrow; + short vcol; + Boolean atEOL; + Boolean impInd; +} Side; + +short helpExtras; +Boolean 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(void); + +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(void) { + 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(void) { + Help_Output(&left, &right); +} + +static void Help_NewLine(void) { + 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 & OTF_HAS_SUB_OPTIONS)) { + 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 & OTF_STICKY) + 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 & OTF_STICKY) && !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 & OTF_HIDE_DEFAULT)) { + 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 & OTF_HIDE_DEFAULT)) { + 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 & OTF_HAS_SUB_OPTIONS) && opt->sub) { + if (!allNoArgs) { + Side_Print( + &left, + "%s", + (opt->avail & OTF_SUB_OPTIONS_OPTIONAL) ? ((lastparam->flags & PARAMFLAGS_8) ? "[=" : "[,") : ((lastparam->flags & PARAMFLAGS_8) ? "=" : ",") + ); + } else if (!(opt->avail & OTF_STICKY)) { + if (opt->avail & OTF_SUB_OPTIONS_OPTIONAL) { + 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 & OTF_SUB_OPTIONS_OPTIONAL) { + 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 & OTF_SUB_OPTIONS_OPTIONAL) ? "]" : "" + ); + + Side_Print(&left, "\t"); + Side_Print(&right, "\t"); + Help_Options(opt->sub, 1, ""); + Side_Print(&right, "\b"); + Side_Print(&left, "\b"); + } else { + Side_Print(&left, "\n"); + Side_Print(&right, "\n"); + } + } + + Help_Flush(); + return 1; +} + +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() == 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(void) { + 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(void) { + 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(void) { + 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(void) { + ShowTextHandle(0, helptext); + DisposeHandle(helptext); +} diff --git a/command_line/C++_Parser/Src/Library/IO.c b/command_line/C++_Parser/Src/Library/IO.c new file mode 100644 index 0000000..36d809b --- /dev/null +++ b/command_line/C++_Parser/Src/Library/IO.c @@ -0,0 +1,83 @@ +#include "parser.h" + +void ShowTextHandle(const char *description, Handle text) { + CWMemHandle mh; + + if (!text) + return; + + if (description) + CLPStatus(71, description); + CWSecretAttachHandle(parseopts.context, text, &mh); + CWParserDisplayTextHandle(parseopts.context, description, mh); +} + +void ShowVersion(Boolean decorate) { + char *vplugin; + char *valtplugin; + const char *bdate; + const char *btime; + Handle txt; + int x; + + vplugin = 0; + valtplugin = 0; + if (parseopts.printedVersion) + return; + + txt = NewHandle(0); + if (!txt) { + fprintf(stderr, "\n*** Out of memory\n"); + exit(-23); + } + + for (x = 0; x < parseopts.numPlugins; x++) { + if (parseopts.plugins[x].plugintype == CWDROPINDRIVERTYPE) continue; + if (parseopts.plugins[x].plugintype == CWDROPINPARSERTYPE) continue; + + if (pTool->TYPE == parseopts.plugins[x].plugintype) { + if (!vplugin && pTool->LANG == parseopts.plugins[x].language) + vplugin = parseopts.plugins[x].version; + else + valtplugin = parseopts.plugins[x].version; + } + } + + CWParserGetBuildDate(parseopts.context, &bdate, &btime); + HPrintF(txt, "\n"); + if (parseopts.toolVersion) { + HPrintF( + txt, + "%s.\n%s, %s\nAll rights reserved.\n%s\n", + pTool->toolInfo, + parseopts.toolVersion->copyright, + parseopts.toolVersion->company, + parseopts.toolVersion->version + ); + } else { + HPrintF( + txt, + "%s.\nCopyright (c)%s Metrowerks, Inc.\nAll rights reserved.\n%s\n", + pTool->toolInfo, + pTool->copyright, + vplugin ? vplugin : valtplugin ? valtplugin : "" + ); + } + + HPrintF(txt, "Runtime Built: %s %s\n", bdate, btime); + HPrintF(txt, "\n"); + + if (decorate) { + HPrintF( + txt, + "Please enter '%s %chelp' for information about options.\n\n", + OS_GetFileNamePtr(parseopts.args->argv[0]), + MAINOPTCHAR[0] + ); + } + + ShowTextHandle(0, txt); + DisposeHandle(txt); + + parseopts.printedVersion = 1; +} diff --git a/command_line/C++_Parser/Src/Library/OptimizerHelpers.c b/command_line/C++_Parser/Src/Library/OptimizerHelpers.c new file mode 100644 index 0000000..4085363 --- /dev/null +++ b/command_line/C++_Parser/Src/Library/OptimizerHelpers.c @@ -0,0 +1,166 @@ +#include "parser.h" + +Boolean setOldOptimizerOptions; + +typedef struct { + Boolean commonsubs; + Boolean loopinvariants; + Boolean propagation; + Boolean deadstore; + Boolean strengthreduction; + Boolean deadcode; + Boolean lifetimes; +} PIROptimizer; // assumed name + +static PIROptimizer pIrOptimizer = {0}; + +Pragma irPragmas[] = { + &pIrOptimizer.commonsubs, "opt_common_subs", 0, + &pIrOptimizer.loopinvariants, "opt_loop_invariants", 0, + &pIrOptimizer.propagation, "opt_propagation", 0, + &pIrOptimizer.deadstore, "opt_dead_assignments", 0, + &pIrOptimizer.deadcode, "opt_dead_code", 0, + &pIrOptimizer.strengthreduction, "opt_strength_reduction", 0, + &pIrOptimizer.lifetimes, "opt_lifetimes", 0, + 0, 0, 0 +}; + +int SetPragmaOptimizationsToUnspecified(const char *opt, void *, const char *, int) { + if (setOldOptimizerOptions) + Option_Warning(CLPStr62); + + memset(&pIrOptimizer, 0, sizeof(pIrOptimizer)); + TargetSetPragmaOptimizationsToUnspecified(); + return 1; +} + +int SetOptFlags(const char *opt, void *str, const char *, int flags) { + // this is very similar to ToolHelper + // might also fail to match + unsigned char *ptr; + Boolean set; + Boolean no; + UInt16 flag; + + ptr = (unsigned char *) str; + no = (Boolean) ((flags & PARAMPARSEFLAGS_8) >> 3); + set = (Boolean) (no ^ 1); + + while (*ptr) { + if (*ptr == '+') { + set = !no; + } else if (*ptr == '-') { + set = no; + } else if (*ptr == '|') { + set = (Boolean) (no ^ 1); + } else { + flag = (ptr[0] << 8) | ptr[1]; + + if ((flag >= 'G0' && flag <= 'G4') || (flag == 'Gs') || (flag == 'Gp')) + SetPragmaOptimizationsToUnspecified(opt, NULL, NULL, 0); + + switch (flag) { + case 'Cs': + pIrOptimizer.commonsubs = set ? 1 : 2; + setOldOptimizerOptions = 1; + break; + case 'Li': + pIrOptimizer.loopinvariants = set ? 1 : 2; + setOldOptimizerOptions = 1; + break; + case 'Pr': + pIrOptimizer.propagation = set ? 1 : 2; + setOldOptimizerOptions = 1; + break; + case 'Ds': + pIrOptimizer.deadstore = set ? 1 : 2; + setOldOptimizerOptions = 1; + break; + case 'Sr': + pIrOptimizer.strengthreduction = set ? 1 : 2; + setOldOptimizerOptions = 1; + break; + case 'Dc': + pIrOptimizer.deadcode = set ? 1 : 2; + setOldOptimizerOptions = 1; + break; + case 'Lt': + pIrOptimizer.lifetimes = set ? 1 : 2; + setOldOptimizerOptions = 1; + break; + case 'G0': + pGlobalOptimizer.optimizationlevel = set ? 0 : 0; + break; + case 'G1': + pGlobalOptimizer.optimizationlevel = set ? 1 : 0; + break; + case 'G2': + pGlobalOptimizer.optimizationlevel = set ? 2 : 0; + break; + case 'G3': + pGlobalOptimizer.optimizationlevel = set ? 3 : 0; + break; + case 'G4': + pGlobalOptimizer.optimizationlevel = set ? 4 : 0; + break; + case 'Gs': + pGlobalOptimizer.optfor = set ? 1 : 0; + break; + case 'Gp': + pGlobalOptimizer.optfor = set ? 0 : 1; + break; + default: + if (!TargetSetOptFlags(flag, set)) + CLPFatalError("Bad optimizer settings in %s (%c%c)\n", str, ptr[0], ptr[1]); + } + + ++ptr; + } + + ++ptr; + } + + return 1; +} + +int DisplayOptimizationOptions(const char *, void *, const char *, int) { + SInt32 oldsize; + Handle h; + + h = NewHandle(0); + if (!h) + exit(-23); + + HPrintF(h, "\t- global optimizer level %d\n", pGlobalOptimizer.optimizationlevel); + HPrintF(h, "\t- global optimize for %s\n", (pGlobalOptimizer.optfor == 0) ? "speed" : "size"); + + oldsize = GetHandleSize(h); + if (pIrOptimizer.commonsubs) + HPrintF(h, "\t- common subexpression elimination %s\n", (pIrOptimizer.commonsubs == 1) ? "on" : "off"); + if (pIrOptimizer.loopinvariants) + HPrintF(h, "\t- loop invariants %s\n", (pIrOptimizer.loopinvariants == 1) ? "on" : "off"); + if (pIrOptimizer.commonsubs) + HPrintF(h, "\t- constant propagation %s\n", (pIrOptimizer.propagation == 1) ? "on" : "off"); + if (pIrOptimizer.deadstore) + HPrintF(h, "\t- dead store elimination %s\n", (pIrOptimizer.deadstore == 1) ? "on" : "off"); + if (pIrOptimizer.deadcode) + HPrintF(h, "\t- dead code elimination %s\n", (pIrOptimizer.deadcode == 1) ? "on" : "off"); + if (pIrOptimizer.strengthreduction) + HPrintF(h, "\t- strength reduction %s\n", (pIrOptimizer.strengthreduction == 1) ? "on" : "off"); + if (pIrOptimizer.lifetimes) + HPrintF(h, "\t- variable lifetimes %s\n", (pIrOptimizer.lifetimes == 1) ? "on" : "off"); + + if (oldsize == GetHandleSize(h)) + HPrintF(h, "\t- no extra global optimizations\n"); + + HPrintF(h, "Backend-specific optimizer options:\n"); + + oldsize = GetHandleSize(h); + TargetDisplayOptimizationOptions(h); + if (oldsize == GetHandleSize(h)) + HPrintF(h, "\t- no extra backend-specific optimizations\n"); + + ShowTextHandle(NULL, h); + DisposeHandle(h); + return 1; +} diff --git a/command_line/C++_Parser/Src/Library/Option.c b/command_line/C++_Parser/Src/Library/Option.c new file mode 100644 index 0000000..2a53f38 --- /dev/null +++ b/command_line/C++_Parser/Src/Library/Option.c @@ -0,0 +1,1136 @@ +#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<MAXSTACK); + if (oStackPtr > 0) { + short prev = + (flags & ARGFLAG_1) ? ARGFLAG_2 : + (flags & ARGFLAG_2) ? ARGFLAG_1 : + (flags & ARGFLAG_4) ? ARGFLAG_2 : -1; + OS_ASSERT(111, 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) { + OS_ASSERT(122, oStackPtr>0); + --oStackPtr; + OS_ASSERT(124, 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] = { + ATK_END, ATK_END, ATK_END, + ATK_ARG_END, ATK_COMMA, ATK_OPTION, + ATK_COMMA, ATK_END, ATK_END, + ATK_EQUALS, ATK_END, ATK_END, + ATK_END, ATK_END, ATK_END +}; +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); +} diff --git a/command_line/C++_Parser/Src/Library/Parameter.c b/command_line/C++_Parser/Src/Library/Parameter.c new file mode 100644 index 0000000..31669e1 --- /dev/null +++ b/command_line/C++_Parser/Src/Library/Parameter.c @@ -0,0 +1,1145 @@ +#include "parser.h" + +char curparam[4096]; +char *descparam = &curparam[0]; +char *helpparam = &curparam[1024]; +char *defaultparam = &curparam[2048]; + +#define copy_8(dst, src) \ +do { \ +((unsigned char *) (dst))[0] = ((unsigned char *) (src))[0]; \ +} while (0) + +#define copy_16(dst, src) \ +do { \ +((unsigned char *) (dst))[0] = ((unsigned char *) (src))[0]; \ +((unsigned char *) (dst))[1] = ((unsigned char *) (src))[1]; \ +} while (0) + +#define copy_32(dst, src) \ +do { \ +((unsigned char *) (dst))[0] = ((unsigned char *) (src))[0]; \ +((unsigned char *) (dst))[1] = ((unsigned char *) (src))[1]; \ +((unsigned char *) (dst))[2] = ((unsigned char *) (src))[2]; \ +((unsigned char *) (dst))[3] = ((unsigned char *) (src))[3]; \ +} while (0) + +#define inline_write_32(dst, val) do { \ +union {unsigned char bytes[4]; unsigned long lg;} _val, _arg; \ +copy_32(_arg.bytes, val); \ +_val.lg = _arg.lg; \ +copy_32(dst, _val.bytes); \ +} while (0) + +#define inline_write_16(dst, val) do { \ +union {unsigned char bytes[2]; unsigned short sh;} _val, _arg; \ +copy_16(_arg.bytes, val); \ +_val.sh = _arg.sh; \ +copy_16(dst, _val.bytes); \ +} while (0) + +#define inline_write_8(ptr, val) copy_8(ptr, val) + +#define inline_andor_32(dst, and, or) do { \ +union {unsigned char bytes[4]; unsigned long lg;} _val, _arg, _arg2; \ +copy_32(_val.bytes, dst); \ +copy_32(_arg.bytes, and); \ +copy_32(_arg2.bytes, or); \ +_val.lg = (_val.lg & ~_arg.lg) | _arg2.lg; \ +copy_32(dst, _val.bytes); \ +} while(0) + +#define inline_andor_16(dst, and, or) do { \ +union {unsigned char bytes[2]; unsigned short sh;} _val, _arg, _arg2; \ +copy_16(_val.bytes, dst); \ +copy_16(_arg.bytes, and); \ +copy_16(_arg2.bytes, or); \ +_val.sh = (_val.sh & ~_arg.sh) | _arg2.sh; \ +copy_16(dst, _val.bytes); \ +} while(0) + +#define inline_andor_8(dst, and, or) do { \ +((unsigned char *) (dst))[0] = (((unsigned char *) (dst))[0] & ~((unsigned char *) (and))[0]) | ((unsigned char *) (or))[0]; \ +} while(0) + +#define inline_xor_32(dst, arg) do { \ +union {unsigned char bytes[4]; unsigned long lg;} _val, _arg; \ +copy_32(_val.bytes, dst); \ +copy_32(_arg.bytes, arg); \ +_val.lg = _val.lg ^ _arg.lg; \ +copy_32(dst, _val.bytes); \ +} while(0) + +#define inline_xor_16(dst, arg) do { \ +union {unsigned char bytes[2]; unsigned short sh;} _val, _arg; \ +copy_16(_val.bytes, dst); \ +copy_16(_arg.bytes, arg); \ +_val.sh = _val.sh ^ _arg.sh; \ +copy_16(dst, _val.bytes); \ +} while(0) + +#define inline_xor_8(dst, arg) do { \ +((unsigned char *) (dst))[0] = (((unsigned char *) (dst))[0] ^ ((unsigned char *) (arg))[0]); \ +} while(0) + +// forward declaration +static int Param_GetArgument(PARAM_T *param, const char **cparam, int exec); +static int Param_Parse(PARAM_T *param, const char *cparam, int flags); + +static int Param_None(PARAM_T *p, const char *pstr, int flags) { + return 1; +} + +static void DescHelpParam_None(PARAM_T *p, const char **desc, const char **help, const char **defaul) { + *desc = 0; + *help = 0; + *defaul = 0; +} + +static int CompareParam_None(PARAM_T *p) { + return 0; +} + +static void DescHelpParam_Number(NUM_T *p, const char **desc, const char **help, const char **defaul) { + unsigned long value; + unsigned char value8; + unsigned short value16; + + value = 0; + *desc = 0; + if (p->myname) + *desc = p->myname; + + if (p->size == 1) { + if (!*desc) + *desc = "byte"; + if (p->num) copy_8(&value8, p->num); + value = value8; + } else if (p->size == 2) { + if (!*desc) + *desc = "short"; + if (p->num) copy_16(&value16, p->num); + value = value16; + } else if (p->size == 4) { + if (!*desc) + *desc = "long"; + if (p->num) copy_32(&value, p->num); + } + + if (p->size == 4) { + if (p->lo != p->hi) + sprintf(helpparam, "range 0x%x - 0x%x", p->lo, p->hi); + *help = helpparam; + if (value <= 0x10000) + sprintf(defaultparam, "%u", value); + else + sprintf(defaultparam, "0x%x", value); + *defaul = defaultparam; + } else { + if (p->lo != p->hi) + sprintf(helpparam, "range %u - %u", p->lo, p->hi); + *help = helpparam; + sprintf(defaultparam, "%u", value); + *defaul = defaultparam; + } + + if (!p->num) + *defaul = 0; + if (p->lo == p->hi) + *help = 0; +} + +static int CompareParam_Number(NUM_T *p) { + return 0; +} + +static int Param_Number(NUM_T *p, const char *pstr, int flags) { + unsigned long val; + unsigned long lo; + unsigned long hi; + const char *opstr; + + val = 0; + opstr = pstr; + if (!pstr[0]) { + Param_Error(5, "", pstr); + return 0; + } + + if (((*pstr == '0') && my_tolower(pstr[1]) == 'x') || (*pstr == '$')) { + // 218 + if (pstr[0] == '$') + pstr += 1; + else + pstr += 2; + + while (*pstr) { + if (!my_isxdigit(*pstr)) { + Param_Error(5, "hexadecimal ", opstr); + return 0; + } + + if (val > 0xFFFFFFF) { + Param_Error(4, opstr); + return 0; + } + + val = (val << 4) | (my_isdigit(*pstr) ? (*pstr - '0') : (my_tolower(*pstr) - 'a' + 10)); + ++pstr; + } + } else if (pstr[0] == '0') { + pstr += 1; + + while (*pstr) { + if (*pstr < '0' || *pstr >= '8') { + Param_Error(5, "octal ", opstr); + return 0; + } + + if (val > 0x1FFFFFFF) { + Param_Error(4, opstr); + return 0; + } + + val = (val << 3) | (*pstr - '0'); + ++pstr; + } + } else { + while (*pstr) { + if (!my_isdigit(*pstr)) { + Param_Error(5, "decimal ", opstr); + return 0; + } + + if (val > 0x19999999) { + Param_Error(4, opstr); + return 0; + } + + val = (val * 10) + (*pstr - '0'); + ++pstr; + } + } + + if (p->lo == p->hi) { + if (p->size == 1) { + lo = 0; + hi = 0xFF; + } else if (p->size == 2) { + lo = 0; + hi = 0xFFFF; + } else { + lo = 0; + hi = 0xFFFFFFFF; + } + } else { + lo = p->lo; + hi = p->hi; + } + + if (!p->fit && (val < lo || val > hi)) { + Param_Error(6, val, lo, hi); + return 0; + } + + if (val < lo) { + Param_Warning(7, val, lo, hi, lo); + val = lo; + } else if (val > hi) { + Param_Warning(7, val, lo, hi, hi); + val = hi; + } + + if (p->size == 1) { + unsigned char val8 = val; + inline_write_8(p->num, &val8); + } + + if (p->size == 2) { + unsigned short val16 = val; + inline_write_16(p->num, &val16); + } else if (p->size == 4) { + unsigned long val32 = val; + inline_write_32(p->num, &val32); + } + + return 1; +} + +static void DescHelpParam_FTypeCreator(FTYPE_T *p, const char **desc, const char **help, const char **defaul) { + if (p->myname) + *desc = p->myname; + else if (p->iscreator) + *desc = "creator"; + else + *desc = "type"; + + if (!p->fc) { + *defaul = 0; + } else { + unsigned long tmp; + unsigned char *ptr; + + ptr = (unsigned char *) defaultparam; + tmp = *p->fc; + ptr[0] = '\''; + ptr[1] = tmp & 0xFF; + ptr[2] = (tmp >> 8) & 0xFF; + ptr[3] = (tmp >> 16) & 0xFF; + ptr[4] = (tmp >> 24) & 0xFF; + ptr[5] = '\''; + ptr[6] = 0; + *defaul = defaultparam; + } +} + +static int CompareParam_FTypeCreator(FTYPE_T *p) { + return 0; +} + +static int Param_FTypeCreator(FTYPE_T *p, const char *pstr, int flags) { + char x[4] = " "; + int cnt; + const char *opstr; + + cnt = 0; + opstr = pstr; + while (*pstr && cnt < 4) { + x[cnt++] = *(pstr++); + } + + if (*pstr) { + Param_Error(8, opstr); + return 0; + } + + inline_write_32(p->fc, &x); + return 1; +} + +static void DescHelpParam_String(STRING_T *p, const char **desc, const char **help, const char **defaul) { + if (p->myname) + *desc = p->myname; + else + *desc = "string"; + + if (!p->str) { + *help = 0; + *defaul = 0; + } else { + sprintf(helpparam, "maximum length %d chars", p->maxlen - 1); + *help = helpparam; + + if (*p->str) { + sprintf(defaultparam, "'%s'", p->str); + *defaul = defaultparam; + } else { + *defaul = "none"; + } + } +} + +static int CompareParam_String(STRING_T *p) { + return 0; +} + +static int Param_String(STRING_T *p, const char *pstr, int flags) { + int len; + + len = strlen(pstr); + strncpy(p->str, pstr, p->maxlen - 1); + if (p->pstring) + c2pstr(p->str); + + if (len > p->maxlen) { + Param_Error(9, pstr, pstr + len - 5, p->maxlen - 1); + return 0; + } + + return 1; +} + +static void DescHelpParam_ID_or_SYM(STRING_T *p, const char **desc, const char **help, const char **defaul) { + if (p->myname) + *desc = p->myname; + else if (p->which == PARAMWHICH_Id) + *desc = "identifier"; + else + *desc = "symbol"; + + if (!p->str) { + *help = *defaul = 0; + } else { + sprintf(helpparam, "maximum length %d chars", p->maxlen - 1); + *help = helpparam; + + if (*p->str) { + sprintf(defaultparam, "'%s'", p->str); + *defaul = defaultparam; + } else { + *defaul = "none"; + } + } +} + +static int CompareParam_ID_or_SYM(STRING_T *p) { + return 0; +} + +static int Param_ID_or_SYM(STRING_T *p, const char *pstr, int flags) { + const char *ptr; + const char *x; + + if (Param_String(p, pstr, flags)) { + if (p->which == PARAMWHICH_Id) { + x = "$_"; + } else if (p->which == PARAMWHICH_Sym) { + x = "_.$@?#"; + } + + for (ptr = pstr; *ptr; ++ptr) { + if (ptr == pstr && my_isdigit(*ptr)) + Param_Warning(10, pstr); + + if (!my_isalnum(*ptr) && !strchr(x, *ptr)) + Param_Warning(11, pstr, *ptr); + } + + return 1; + } else { + return 0; + } +} + +static void DescHelpParam_OnOff(ONOFF_T *p, const char **desc, const char **help, const char **defaul) { + unsigned char def; + + if (p->myname) + *desc = p->myname; + else + *desc = "on|off"; + + *help = 0; + if (!p->var) { + *defaul = 0; + } else { + if (p->var) + *((unsigned char *) &def) = *((unsigned char *) p->var); + if (def) + *defaul = "on"; + else + *defaul = "off"; + } +} + +static int CompareParam_OnOff(ONOFF_T *p) { + return 0; +} + +static int Param_OnOff(ONOFF_T *p, const char *pstr, int flags) { + Boolean mytrue = (flags & PARAMPARSEFLAGS_8) == 0; + + if (!ustrcmp(pstr, "on")) { + *(p->var) = mytrue; + } else if (!ustrcmp(pstr, "off")) { + *(p->var) = mytrue == 0; + } else { + Param_Error(12, pstr); + return 0; + } + + return 1; +} + +static void DescHelpParam_OffOn(ONOFF_T *p, const char **desc, const char **help, const char **defaul) { + unsigned char def; + + if (p->myname) + *desc = p->myname; + else + *desc = "off|on"; + + *help = 0; + if (!p->var) { + *defaul = 0; + } else { + if (p->var) + *((unsigned char *) &def) = *((unsigned char *) p->var); + if (!def) + *defaul = "on"; + else + *defaul = "off"; + } +} + +static int CompareParam_OffOn(OFFON_T *p) { + return 0; +} + +static int Param_OffOn(OFFON_T *p, const char *pstr, int flags) { + Boolean mytrue = (flags & PARAMPARSEFLAGS_8) == 0; + + if (!ustrcmp(pstr, "off")) { + *(p->var) = mytrue; + } else if (!ustrcmp(pstr, "on")) { + *(p->var) = mytrue == 0; + } else { + Param_Error(12, pstr); + return 0; + } + + return 1; +} + +static void DescHelpParam_FilePath(FILEPATH_T *p, const char **desc, const char **help, const char **defaul) { + if (p->myname) + *desc = p->myname; + else + *desc = "filepath"; + + *help = 0; + *defaul = p->defaultstr; +} + +static int CompareParam_FilePath(FILEPATH_T *p) { + return 0; +} + +static int Param_FilePath(FILEPATH_T *p, const char *pstr, int flags) { + int err; + OSSpec spec; + char canon[256]; + int clen; + + if (!pstr[0]) { + ((unsigned char *) p->filename)[0] = 0; + return 1; + } + + err = OS_MakeFileSpec(pstr, &spec); + if (err) { + Param_Error(18, pstr, OS_GetErrText(err)); + return 0; + } + + OS_SpecToString(&spec, canon, sizeof(canon)); + if (p->fflags & 1) { + c2pstrcpy(p->filename, canon); + } else { + clen = strlen(canon); + if (clen > p->maxlen) { + Param_Error(13, canon + clen - 32, canon); + return 0; + } + strcpy(p->filename, canon); + } + + return 1; +} + +static void DescHelpParam_Mask(MASK_T *p, const char **desc, const char **help, const char **defaul) { + *help = 0; + *desc = 0; + *defaul = 0; +} + +static int CompareParam_Mask(MASK_T *p) { + if (p->size == 1) { + unsigned char or8 = p->ormask, and8 = p->andmask, val8; + if (p->num) copy_8(&val8, p->num); + return ((val8 & ~and8) | or8) == val8; + } else if (p->size == 2) { + unsigned short or16 = p->ormask, and16 = p->andmask, val16; + if (p->num) copy_16(&val16, p->num); + return ((val16 & ~and16) | or16) == val16; + } else { + unsigned long or32 = p->ormask, and32 = p->andmask, val32; + if (p->num) copy_32(&val32, p->num); + return ((val32 & ~and32) | or32) == val32; + } +} + +static int Param_Mask(MASK_T *p, const char *pstr, int flags) { + if (p->size == 1) { + unsigned char or8 = p->ormask, and8 = p->andmask, tmp8; + if (flags & PARAMPARSEFLAGS_8) { + tmp8 = and8; + and8 = and8 | or8; + or8 = tmp8; + } + inline_andor_8(p->num, &and8, &or8); + } else if (p->size == 2) { + unsigned short or16 = p->ormask, and16 = p->andmask, tmp16; + if (flags & PARAMPARSEFLAGS_8) { + tmp16 = and16; + and16 = and16 | or16; + or16 = tmp16; + } + inline_andor_16(p->num, &and16, &or16); + } else { + unsigned long or32 = p->ormask, and32 = p->andmask, tmp32; + if (flags & PARAMPARSEFLAGS_8) { + tmp32 = and32; + and32 = and32 | or32; + or32 = tmp32; + } + inline_andor_32(p->num, &and32, &or32); + } + return 1; +} + +static void DescHelpParam_Toggle(TOGGLE_T *p, const char **desc, const char **help, const char **defaul) { + *help = 0; + *desc = 0; + *defaul = 0; +} + +static int CompareParam_Toggle(TOGGLE_T *p) { + if (p->size == 1) { + unsigned char mask8, val8; + mask8 = (unsigned char) p->mask; + if (p->num) copy_8(&val8, p->num); + return (val8 ^ mask8) == val8; + } else if (p->size == 2) { + unsigned short mask16, val16; + mask16 = (unsigned short) p->mask; + if (p->num) copy_16(&val16, p->num); + return (val16 ^ mask16) == val16; + } else { + unsigned long mask32, val32; + mask32 = p->mask; + if (p->num) copy_16(&val32, p->num); // BUG ALERT + return (val32 ^ mask32) == val32; + } +} + +static int Param_Toggle(TOGGLE_T *p, const char *pstr, int flags) { + if (p->size == 1) { + unsigned char val8; + val8 = (unsigned char) p->mask; + inline_xor_8(p->num, &val8); + } else if (p->size == 2) { + unsigned short val16; + val16 = (unsigned short) p->mask; + inline_xor_16(p->num, &val16); + } else { + inline_xor_32(p->num, &p->mask); + } + return 1; +} + +static void DescHelpParam_Set(SET_T *p, const char **desc, const char **help, const char **defaul) { + *help = 0; + *desc = 0; + *defaul = 0; +} + +static int CompareParam_Set(SET_T *p) { + if (p->size == 1) { + unsigned char set8, val8; + set8 = (unsigned char) p->value; + if (p->num) copy_8(&val8, p->num); + return set8 == val8; + } else if (p->size == 2) { + unsigned short set16, val16; + set16 = (unsigned short) p->value; + if (p->num) copy_16(&val16, p->num); + return set16 == val16; + } else { + unsigned long set32, val32; + set32 = p->value; + if (p->num) copy_32(&val32, p->num); + return set32 == val32; + } +} + +static int Param_Set(SET_T *p, const char *pstr, int flags) { + if (p->size == 1) { + unsigned char val8; + val8 = (unsigned char) p->value; + if ((flags & PARAMPARSEFLAGS_8) && val8 <= 1) + val8 = (val8 == 0); + inline_write_8(p->num, &val8); + } else if (p->size == 2) { + unsigned short val16; + val16 = (unsigned short) p->value; + if ((flags & PARAMPARSEFLAGS_8) && val16 <= 1) + val16 = (val16 == 0); + inline_write_16(p->num, &val16); + } else { + unsigned long val32; + val32 = p->value; + if ((flags & PARAMPARSEFLAGS_8) && val32 <= 1) + val32 = (val32 == 0); + inline_write_32(p->num, &val32); + } + return 1; +} + +static void DescHelpParam_SetString(SETSTRING_T *p, const char **desc, const char **help, const char **defaul) { + *help = 0; + *desc = 0; + *defaul = 0; +} + +static int CompareParam_SetString(SETSTRING_T *p, int flags) { + if (p->pstring) + return pstrcmp((const unsigned char *) p->var, (const unsigned char *) p->value) == 0; + else + return strcmp(p->var, p->value) == 0; +} + +static int Param_SetString(SETSTRING_T *p, const char *pstr, int flags) { + if (p->pstring) + memcpy(p->var, p->value, p->value[0]); + else + strcpy(p->var, p->value); + return 1; +} + +static void DescHelpParam_Generic(GENERIC_T *p, const char **desc, const char **help, const char **defaul) { + if (p->myname) + *desc = p->myname; + else if ((p->flags & PARAMFLAGS_3) != 1) + *desc = "xxx"; + else + *desc = 0; + *help = p->help; + *defaul = 0; +} + +static int CompareParam_Generic(GENERIC_T *p) { + return 0; +} + +static int Param_Generic(GENERIC_T *p, const char *pstr, int flags) { + return p->parse(curopt, p->var, pstr, flags); +} + +static void DescHelpParam_Setting(SETTING_T *p, const char **desc, const char **help, const char **defaul) { + char *dptr = descparam; + + dptr += sprintf(dptr, "%s", p->myname ? p->myname : "var"); + if ((p->flags & PARAMFLAGS_3) != 1) { + sprintf(dptr, + "%s=%s%s", + (p->flags & PARAMFLAGS_2) ? "[" : "", + p->valuename ? p->valuename : "...", + (p->flags & PARAMFLAGS_2) ? "]" : "" + ); + } + *desc = descparam; + *help = 0; + *defaul = 0; +} + +static int CompareParam_Setting(SETTING_T *p) { + return 0; +} + +static int Param_Setting(SETTING_T *p, const char *pstr, int flags) { + char savevar[256]; + const char *vstr; + ArgToken *tok; + Boolean equals = 0; + + if (!pstr) { + Param_Error(40); + return 0; + } + + strncpy(savevar, pstr, sizeof(savevar)); + tok = Arg_PeekToken(); + if (tok && tok->val == ATK_EQUALS) { + Arg_UsedToken(); + equals = 1; + if (!Param_GetArgument((PARAM_T *) p, &vstr, flags)) + return 0; + } else { + vstr = 0; + } + + if (!vstr && equals) + vstr = ""; + + return p->parse(savevar, vstr); +} + +static void DescHelpParam_IfArg(IFARG_T *p, const char **desc, const char **help, const char **defaul) { + const char *d1 = 0; + const char *d2 = 0; + const char *h1 = 0; + const char *h2 = 0; + const char *df1 = 0; + const char *df2 = 0; + char desclocal[1024]; + char *dptr = desclocal; + char helplocal[1024]; + char *hptr = helplocal; + const char *ind; + + desclocal[0] = 0; + helplocal[0] = 0; + + if (p->parg) + Param_DescHelp(p->parg, &d1, &h1, &df1); + if (p->pnone) + Param_DescHelp(p->pnone, &d2, &h2, &df2); + + if (p->helpa && p->helpn) { + if (df1) + hptr += sprintf(hptr, "%s (default is %s), else %s", p->helpa, df1, p->helpn); + else + hptr += sprintf(hptr, "%s, else %s", p->helpa, p->helpn); + } else if (p->helpa) { + hptr += sprintf(hptr, "%s", p->helpa); + if (df1) + hptr += sprintf(hptr, "; default is %s", df1); + } else if (p->helpn) { + hptr += sprintf(hptr, "nothing, else %s", p->helpn); + } + + if (d1) { + if (p->myname) { + dptr += sprintf(dptr, "[%s]", p->myname ? p->myname: "param"); + } else if (h1) { + ind = strchr(d1, '\n'); + if (!ind) + ind = d1 + strlen(d1); + dptr += sprintf(dptr, "[%.*s]", ind - d1, d1); + } else { + dptr += sprintf(dptr, "[%s]", d1); + d1 = 0; + } + } + + if (h1 || h2) { + dptr += sprintf(dptr, "\n\t"); + hptr += sprintf(hptr, "\n\t"); + if (h1) { + if (d1) + dptr += sprintf(dptr, "%s", d1); + if (h1) + hptr += sprintf(hptr, "%s", h1); + if (h2) { + dptr += sprintf(dptr, "\b\t"); + hptr += sprintf(hptr, "\b\t"); + } + } + if (h2) { + if (d2) + dptr += sprintf(dptr, "%s", d2); + else + dptr += sprintf(dptr, "(if blank)"); + if (h2) + hptr += sprintf(hptr, "%s", h2); + dptr += sprintf(dptr, "\n"); + hptr += sprintf(hptr, "\n"); + } + dptr += sprintf(dptr, "\b"); + hptr += sprintf(hptr, "\b"); + } + + if (dptr != desclocal) { + strcpy(descparam, desclocal); + *desc = descparam; + } else { + *desc = 0; + } + + if (hptr != helplocal) { + strcpy(helpparam, helplocal); + *help = helpparam; + } else { + *help = 0; + } + + *defaul = 0; +} + +static int CompareParam_IfArg(IFARG_T *p) { + return 0; +} + +static int Param_IfArg(IFARG_T *p, const char *pstr, int flags) { + if (pstr) + return Param_Parse(p->parg, pstr, flags); + else if (p->pnone) + return Param_Parse(p->pnone, pstr, flags); + else + return 1; +} + +typedef int (*PARSE_FUNC)(PARAM_T *, const char *, int); +PARSE_FUNC ParamParsers[16] = { + (PARSE_FUNC) &Param_None, + (PARSE_FUNC) &Param_FTypeCreator, + (PARSE_FUNC) &Param_FilePath, + (PARSE_FUNC) &Param_Number, + (PARSE_FUNC) &Param_String, + (PARSE_FUNC) &Param_ID_or_SYM, + (PARSE_FUNC) &Param_ID_or_SYM, + (PARSE_FUNC) &Param_OnOff, + (PARSE_FUNC) &Param_OffOn, + (PARSE_FUNC) &Param_Mask, + (PARSE_FUNC) &Param_Toggle, + (PARSE_FUNC) &Param_Set, + (PARSE_FUNC) &Param_SetString, + (PARSE_FUNC) &Param_Generic, + (PARSE_FUNC) &Param_IfArg, + (PARSE_FUNC) &Param_Setting +}; + +static int Param_Parse(PARAM_T *param, const char *cparam, int flags) { + if (!param) + CLPFatalError("PARAM_T is NULL"); + + if (param->which >= PARAMWHICH_None && param->which < PARAMWHICH_MAX) { + return ParamParsers[param->which](param, cparam, flags); + } else { + CLPFatalError("Unhandled PARAM_T (%d)", param->which); + return 0; + } +} + +typedef void (*DESC_HELP_FUNC)(PARAM_T *, const char **, const char **, const char **); +DESC_HELP_FUNC DescHelpParams[16] = { + (DESC_HELP_FUNC) &DescHelpParam_None, + (DESC_HELP_FUNC) &DescHelpParam_FTypeCreator, + (DESC_HELP_FUNC) &DescHelpParam_FilePath, + (DESC_HELP_FUNC) &DescHelpParam_Number, + (DESC_HELP_FUNC) &DescHelpParam_String, + (DESC_HELP_FUNC) &DescHelpParam_ID_or_SYM, + (DESC_HELP_FUNC) &DescHelpParam_ID_or_SYM, + (DESC_HELP_FUNC) &DescHelpParam_OnOff, + (DESC_HELP_FUNC) &DescHelpParam_OffOn, + (DESC_HELP_FUNC) &DescHelpParam_Mask, + (DESC_HELP_FUNC) &DescHelpParam_Toggle, + (DESC_HELP_FUNC) &DescHelpParam_Set, + (DESC_HELP_FUNC) &DescHelpParam_SetString, + (DESC_HELP_FUNC) &DescHelpParam_Generic, + (DESC_HELP_FUNC) &DescHelpParam_IfArg, + (DESC_HELP_FUNC) &DescHelpParam_Setting +}; +void Param_DescHelp(PARAM_T *param, const char **desc, const char **help, const char **defaul) { + *desc = 0; + *help = 0; + *defaul = 0; + + if (!param) { + CLPFatalError("PARAM_T is NULL"); + return; + } + + if (param->which >= PARAMWHICH_None && param->which < PARAMWHICH_MAX) { + DescHelpParams[param->which](param, desc, help, defaul); + } else { + CLPFatalError("Unhandled PARAM_T (%d)", param->which); + } +} + +typedef int (*COMPARE_FUNC)(PARAM_T *); +COMPARE_FUNC CompareParams[16] = { + (COMPARE_FUNC) &CompareParam_None, + (COMPARE_FUNC) &CompareParam_FTypeCreator, + (COMPARE_FUNC) &CompareParam_FilePath, + (COMPARE_FUNC) &CompareParam_Number, + (COMPARE_FUNC) &CompareParam_String, + (COMPARE_FUNC) &CompareParam_ID_or_SYM, + (COMPARE_FUNC) &CompareParam_ID_or_SYM, + (COMPARE_FUNC) &CompareParam_OnOff, + (COMPARE_FUNC) &CompareParam_OffOn, + (COMPARE_FUNC) &CompareParam_Mask, + (COMPARE_FUNC) &CompareParam_Toggle, + (COMPARE_FUNC) &CompareParam_Set, + (COMPARE_FUNC) &CompareParam_SetString, + (COMPARE_FUNC) &CompareParam_Generic, + (COMPARE_FUNC) &CompareParam_IfArg, + (COMPARE_FUNC) &CompareParam_Setting +}; +int Param_Compare(PARAM_T *param) { + if (!param) + CLPFatalError("PARAM_T is NULL"); + + if (param->which >= PARAMWHICH_None && param->which < PARAMWHICH_MAX) { + return CompareParams[param->which](param); + } else { + CLPFatalError("Unhandled PARAM_T (%d)", param->which); + return 0; + } +} + +static void Param_PushParam(const char *param) { + Args_Push(4, (void *) param, 0); +} + +static void Param_PopParam(void) { + Args_Pop(4); +} + +static Boolean Param_IsNonTextFile(const char *fname, Boolean warn) { + OSSpec tmp; + CWDataType mactype; + Boolean isfile; + + if (!OS_MakeSpec(fname, &tmp, &isfile)) { + if (isfile) { + if (!OS_Status(&tmp)) { + if (!OS_GetMacFileType(&tmp, &mactype)) { + if (mactype != 'TEXT') { + if (warn) + Param_Warning(77, fname); + return 1; + } + } + } + } + } + + return 0; +} + +static int Param_GetArgument(PARAM_T *param, const char **cparam, int exec) { + int subparse; + short nextOpt; + short nextParam; + short lastOpt; + ArgToken *tok; + + subparse = (exec & PARAMPARSEFLAGS_4) != 0; + nextOpt = !subparse ? ATK_ARG_END : ATK_COMMA; + nextParam = !subparse ? ATK_COMMA : ATK_EQUALS; + lastOpt = !subparse ? ATK_END : ATK_ARG_END; + + tok = Arg_PeekToken(); + OS_ASSERT(1467, tok); + + if ((param->flags & PARAMFLAGS_3) == 0) { + if (tok->val == nextParam || tok->val == ATK_EQUALS) + tok = Arg_UsedToken(); + if (tok->val == nextOpt || tok->val == nextParam || tok->val == lastOpt) { + Param_Error(34); + return 0; + } + if (tok->val != ATK_ARG) { + Param_Error(57, "parameter", Arg_GetTokenName(tok)); + return 0; + } + Arg_GetTokenText(tok, curparam, sizeof(curparam), 1); + Arg_UsedToken(); + *cparam = curparam; + + if (param->flags & PARAMFLAGS_8) { + tok = Arg_PeekToken(); + if (tok->val == ATK_EQUALS) + Arg_UsedToken(); + } + } else if (param->flags & PARAMFLAGS_1) { + *cparam = 0; + if (tok->val == ATK_EQUALS && !subparse) { + if (!(exec & PARAMPARSEFLAGS_40)) { + Param_Error(37); + return 0; + } + Arg_UsedToken(); + } + } else if (param->flags & PARAMFLAGS_2) { + if (tok->val == nextOpt || tok->val == lastOpt) { + *cparam = 0; + } else if (tok->val == nextParam) { + tok = Arg_UsedToken(); + if (tok->val == ATK_ARG) { + Arg_GetTokenText(tok, curparam, sizeof(curparam), 1); + if ((param->flags & PARAMFLAGS_12) && Param_IsNonTextFile(curparam, !(exec & PARAMPARSEFLAGS_1))) { + *cparam = 0; + } else { + Arg_UsedToken(); + *cparam = curparam; + } + } else { + *cparam = 0; + } + } else if (tok->val == ATK_ARG && !tok->text[0]) { + tok = Arg_UsedToken(); + if (tok->val == nextParam) + Arg_UsedToken(); + *cparam = 0; + } else if ((exec & PARAMPARSEFLAGS_4) && tok->val != ATK_EQUALS) { + *cparam = 0; + } else { + if (tok->val == ATK_EQUALS) + tok = Arg_UsedToken(); + if (tok->val == ATK_ARG) { + Arg_GetTokenText(tok, curparam, sizeof(curparam), 1); + if ((param->flags & PARAMFLAGS_12) && Param_IsNonTextFile(curparam, !(exec & PARAMPARSEFLAGS_1))) { + *cparam = 0; + } else { + Arg_UsedToken(); + *cparam = curparam; + } + } else { + *cparam = 0; + } + } + } else { + CLPFatalError("Unknown parameter type"); + } + + if (pTool->TYPE == CWDROPINCOMPILERTYPE && (exec & PARAMPARSEFLAGS_2) && *cparam) { + if (!(exec & PARAMPARSEFLAGS_10)) { + if (subparse) + Arg_AddToToolArgs(&linkargs, ATK_EQUALS, 0); + else + Arg_AddToToolArgs(&linkargs, ATK_COMMA, 0); + } + Param_PushParam(*cparam); + Args_AddToToolArgs(&linkargs); + Param_PopParam(); + } + + return 1; +} + +int Params_Parse(PARAM_T *param, int flags) { + const char *cparam; + flags |= PARAMPARSEFLAGS_10; + + if (param) { + while (param) { + if (flags & PARAMPARSEFLAGS_20) + flags |= PARAMPARSEFLAGS_40; + + if (!Param_GetArgument(param, &cparam, flags)) + return 0; + + if (!(flags & PARAMPARSEFLAGS_1)) { + if (!Param_Parse(param, cparam, flags | (short) ((param->flags & PARAMFLAGS_4) ? PARAMPARSEFLAGS_20 : 0))) + return 0; + } else if (param->flags & PARAMFLAGS_4) { + if (!Param_GetArgument(param, &cparam, flags | PARAMPARSEFLAGS_4)) + return 0; + } + + if (cparam) + flags &= ~PARAMPARSEFLAGS_10; + flags &= ~PARAMPARSEFLAGS_40; + param = param->next; + } + } + + return 1; +} + +void Param_Error(short id, ...) { + va_list va; + va_start(va, id); + Option_ParamError(id, va); + va_end(va); +} + +void Param_Warning(short id, ...) { + va_list va; + va_start(va, id); + Option_ParamWarning(id, va); + va_end(va); +} diff --git a/command_line/C++_Parser/Src/Library/ParserErrors.c b/command_line/C++_Parser/Src/Library/ParserErrors.c new file mode 100644 index 0000000..df5e67e --- /dev/null +++ b/command_line/C++_Parser/Src/Library/ParserErrors.c @@ -0,0 +1,119 @@ +#include "parser.h" + +static char errorbuf[1024]; + +void CLPReportError_V(const char *format, va_list ap) { + vsprintf(errorbuf, format, ap); + CWReportMessage(parseopts.context, NULL, errorbuf, NULL, messagetypeError, 0); + parseopts.hadErrors = 1; +} + +void CLPReportWarning_V(const char *format, va_list ap) { + vsprintf(errorbuf, format, ap); + CWReportMessage(parseopts.context, NULL, errorbuf, NULL, messagetypeWarning, 0); +} + +void CLPReport_V(const char *format, va_list ap) { + vsprintf(errorbuf, format, ap); + CWReportMessage(parseopts.context, NULL, errorbuf, NULL, messagetypeInfo, 0); +} + +void CLPStatus_V(const char *format, va_list ap) { + vsprintf(errorbuf, format, ap); + CWShowStatus(parseopts.context, errorbuf, NULL); +} + +void CLPAlert_V(const char *format, va_list ap) { + vsprintf(errorbuf, format, ap); + CWAlert(parseopts.context, errorbuf, NULL, NULL, NULL); + parseopts.hadErrors = 1; +} + +void CLPOSAlert_V(const char *format, SInt32 err, va_list ap) { + vsprintf(errorbuf, format, ap); + CWAlert(parseopts.context, errorbuf, "Operating system error:", OS_GetErrText(err), NULL); +} + +char *CLPGetErrorString(SInt16 errid, char *buffer) { + getindstring(buffer, 12010, errid); + return buffer; +} + +void CLPReportError(SInt16 errid, ...) { + char format[256]; + va_list va; + + CLPGetErrorString(errid, format); + va_start(va, errid); + CLPReportError_V(format, va); + va_end(va); +} + +void CLPReportWarning(SInt16 errid, ...) { + char format[256]; + va_list va; + + CLPGetErrorString(errid, format); + va_start(va, errid); + CLPReportWarning_V(format, va); + va_end(va); +} + +void CLPReport(SInt16 errid, ...) { + char format[256]; + va_list va; + + CLPGetErrorString(errid, format); + va_start(va, errid); + CLPReport_V(format, va); + va_end(va); +} + +void CLPAlert(SInt16 errid, ...) { + char format[256]; + va_list va; + + CLPGetErrorString(errid, format); + va_start(va, errid); + CLPAlert_V(format, va); + va_end(va); +} + +void CLPOSAlert(SInt16 errid, SInt16 err, ...) { + char format[256]; + va_list va; + + CLPGetErrorString(errid, format); + va_start(va, err); + CLPOSAlert_V(format, err, va); + va_end(va); +} + +void CLPProgress(SInt16 errid, ...) { + char format[256]; + va_list va; + + CLPGetErrorString(errid, format); + va_start(va, errid); + CLPStatus_V(format, va); + va_end(va); +} + +void CLPStatus(SInt16 errid, ...) { + char format[256]; + va_list va; + + CLPGetErrorString(errid, format); + va_start(va, errid); + CLPStatus_V(format, va); + va_end(va); +} + +void CLPFatalError(const char *format, ...) { + va_list va; + + va_start(va, format); + CLPAlert_V(format, va); + va_end(va); + longjmp(exit_plugin, -123); +} diff --git a/command_line/C++_Parser/Src/Library/ParserFace.c b/command_line/C++_Parser/Src/Library/ParserFace.c new file mode 100644 index 0000000..a005ece --- /dev/null +++ b/command_line/C++_Parser/Src/Library/ParserFace.c @@ -0,0 +1,298 @@ +#include "parser.h" + +const char *failedCallback; +jmp_buf exit_plugin; +ParseOptsType parseopts; + +static CWResult SetupParamBlock(CWPluginContext context) { + CWResult result; + int x; + Handle h; + PCmdLineEnvir cle; + + memset(&parseopts, 0, sizeof(parseopts)); + parseopts.context = context; + + result = CWSecretGetNamedPreferences(context, "CmdLine Environment", &h); + if (result) + return result; + + cle = **((PCmdLineEnvir **) h); + parseopts.underIDE = cle.underIDE; + parseopts.ioRows = cle.rows; + parseopts.ioCols = cle.cols; + + result = CWParserGetCommandLine(context, &parseopts.args); + if (result) + return result; + + result = CWParserGetToolInfo(context, &parseopts.toolVersion); + if (result) + return result; + + result = CWParserGetTargetInfo(context, &parseopts.cpu, &parseopts.os); + if (result) + return result; + + result = CWParserGetPanels(context, &parseopts.numPanels, &parseopts.panelNames); + if (result) + return result; + + result = CWParserGetPlugins(context, &parseopts.numPlugins, &parseopts.plugins); + if (result) + return result; + + parseopts.passingArgs = 0; + for (x = 0; x < parseopts.numPlugins; x++) { + if (parseopts.plugins[x].storeCommandLine) + parseopts.passingArgs = 1; + } + + return 0; +} + +static CWResult SetupOptions(CWPluginContext context) { + if (!pTool) { + return 2; + } else { + SetupParserToolOptions(); + return 0; + } +} + +static CWResult Parse(CWPluginContext context) { + CWResult result; + + parseopts.success = 1; + parseopts.currentSegment = 1; + parseopts.currentOverlayGroup = 0; + parseopts.currentOverlay = 0; + + Arg_InitToolArgs(&linkargs); + Arg_InitToolArgs(&prelinkargs); + Arg_InitToolArgs(&postlinkargs); + + if (pTool->PreParse) + parseopts.success &= pTool->PreParse(); + + Arg_Init(parseopts.args->argc, parseopts.args->argv); + parseopts.noOptions = Arg_IsEmpty(); + parseopts.success &= Options_Parse(Options_GetOptions(), OFLAGS_1) && !parseopts.hadErrors; + Arg_Reset(); + + result = Parser_StorePanels(context); + if (result) + return result; + + if (pTool->MidParse && parseopts.success) + parseopts.success &= pTool->MidParse(); + + result = Parser_StorePanels(context); + if (result) + return result; + + if (parseopts.showHelp && parseopts.success) + parseopts.success &= Options_DisplayHelp(); + + Arg_Reset(); + if (parseopts.success) + parseopts.success &= Options_Parse(Options_GetOptions(), 0) && !parseopts.hadErrors; + + if (pTool->PostParse && parseopts.success) + parseopts.success &= pTool->PostParse(); + + Arg_Terminate(); + + return (parseopts.success && !parseopts.hadErrors) ? cwNoErr : cwErrRequestFailed; +} + +Handle Parser_FindPrefPanel(const char *name) { + int idx; + Handle h; + + for (idx = 0; idx < pTool->numPrefDataPanels; idx++) { + if (!ustrcmp(name, pTool->prefDataPanels[idx].name)) { + h = NewHandle(pTool->prefDataPanels[idx].size); + if (!h) + return NULL; + + HLock(h); + memcpy(*h, pTool->prefDataPanels[idx].ptr, pTool->prefDataPanels[idx].size); + HUnlock(h); + return h; + } + } + + return NULL; +} + +CWResult Parser_StorePanels(CWPluginContext context) { + int idx; + CWResult result; + const char *name; + Handle h; + + for (idx = 0; idx < parseopts.numPanels; idx++) { + name = parseopts.panelNames[idx]; + h = Parser_FindPrefPanel(name); + if (h) { + result = CWParserSetNamedPreferences(parseopts.context, name, h); + if (result) { + CLPReportError(CLPStr68, name); + return result; + } + } + } + + return cwNoErr; +} + +static CWResult StoreResults(CWPluginContext context) { + int idx; // r25 + CWResult result; + CWCommandLineArgs args; + UInt32 id; // r8 + UInt32 lg; // r10 + + result = Parser_StorePanels(context); + if (result) + return result; + + for (idx = 0; idx < parseopts.numPlugins; idx++) { + if (parseopts.plugins[idx].plugintype == CWDROPINLINKERTYPE && parseopts.plugins[idx].storeCommandLine) { + if (parseopts.plugins[idx].dropinflags & isPreLinker) { + Arg_ToolArgsForPlugin(&prelinkargs, &args); + } else if (parseopts.plugins[idx].dropinflags & isPostLinker) { + Arg_ToolArgsForPlugin(&postlinkargs, &args); + } else { + Arg_ToolArgsForPlugin(&linkargs, &args); + } + result = CWParserStoreCommandLineForPlugin(parseopts.context, idx, &args); + if (result) + return result; + } else if (parseopts.plugins[idx].storeCommandLine) { + id = parseopts.plugins[idx].plugintype; + lg = parseopts.plugins[idx].language; + fprintf(stderr, + "*** No support for %c%c%c%c/%c%c%c%c tool\n", + (id & 0xFF000000) >> 24, + (id & 0x00FF0000) >> 16, + (id & 0x0000FF00) >> 8, + (id & 0x000000FF), + (lg & 0xFF000000) >> 24, + (lg & 0x00FF0000) >> 16, + (lg & 0x0000FF00) >> 8, + (lg & 0x000000FF) + ); + } + } + + return cwNoErr; +} + +CWPLUGIN_ENTRY (CWParser_GetDropInFlags)(const DropInFlags **flags, SInt32 *flagsSize) { + static const DropInFlags sFlags = { + kCurrentDropInFlagsVersion, + CWDROPINPARSERTYPE, + 7, + 0, + 'Seep', + 12 + }; + *flags = &sFlags; + *flagsSize = sizeof(sFlags); + return 0; +} + +CWPLUGIN_ENTRY (CWParser_GetDropInName)(const char **dropinName) { + static const char *sDropInName = "Command-Line Parser"; + *dropinName = sDropInName; + return 0; +} + +CWPLUGIN_ENTRY (CWParser_GetDisplayName)(const char **displayName) { + static const char *sDisplayName = "Command-Line Parser"; + *displayName = sDisplayName; + return 0; +} + +CWPLUGIN_ENTRY (CWParser_GetPanelList)(const CWPanelList **panelList) { + static CWPanelList sPanelList = { + kCurrentCWFamilyListVersion, + 0, + 0 + }; + *panelList = &sPanelList; + return 0; +} + +CWPLUGIN_ENTRY (CWParser_GetTargetList)(const CWTargetList **targetList) { + static CWDataType sCPU = '****'; + static CWDataType sOS = '****'; + static CWTargetList sTargetList = { + kCurrentCWTargetListVersion, + 1, + &sCPU, + 1, + &sOS + }; + *targetList = &sTargetList; + return 0; +} + +CWPLUGIN_ENTRY (CWParser_GetVersionInfo)(const VersionInfo **versioninfo) { + static const VersionInfo vi = { + 1, 1, 0, 0 + }; + *versioninfo = &vi; + return 0; +} + +CWPLUGIN_ENTRY (Parser_SupportsPlugin)(const struct CLPluginInfo *pluginfo, CWDataType cpu, CWDataType os, Boolean *isSupported) { + *isSupported = ParserToolMatchesPlugin(pluginfo->plugintype, pluginfo->language, cpu, os); + return 0; +} + +CWPLUGIN_ENTRY (Parser_SupportsPanels)(int numPanels, const char **panelNames, Boolean *isSupported) { + *isSupported = ParserToolHandlesPanels(numPanels, panelNames); + return 0; +} + +CWPLUGIN_ENTRY (parser_main)(CWPluginContext context) { + CWResult result; + SInt32 request; + + CWGetPluginRequest(context, &request); + result = setjmp(exit_plugin); + if (result == 0) { + switch (request) { + case reqInitialize: + result = 0; + break; + case 0: + break; + case 1: + result = SetupParamBlock(context); + if (!result) + result = Parser_StorePanels(context); + break; + case 2: + result = SetupParamBlock(context); + if (!result) { + result = SetupOptions(context); + if (!result) { + result = Parse(context); + if (!result) + result = StoreResults(context); + } + } + break; + } + } else { + if (failedCallback && result != 1) + fprintf(stderr, "Unexpected error in %s [%d]\n", failedCallback, result); + } + CWDonePluginRequest(context, result); + + return result; +} diff --git a/command_line/C++_Parser/Src/Library/ParserHelpers-cc.c b/command_line/C++_Parser/Src/Library/ParserHelpers-cc.c new file mode 100644 index 0000000..07315b3 --- /dev/null +++ b/command_line/C++_Parser/Src/Library/ParserHelpers-cc.c @@ -0,0 +1,156 @@ +#include "parser.h" + +Handle definesHandle; + +int Opt_AddStringToDefines(const char *opt, void *str, const char *param, int flags) { + AddStringToHandle(&definesHandle, (const char *) str); + if (param) + AddStringToHandle(&definesHandle, param); + return 1; +} + +int Opt_DefineSymbol(const char *var, const char *value) { + char tmp[1024]; + + if (pTool->LANG == Lang_C_CPP || pTool->LANG == CWFOURCHAR('A','s','m',' ') || pTool->LANG == Lang_Rez) { + sprintf(tmp, "#define %s %s\n", var, value ? value : "1"); + } else if (pTool->LANG == Lang_Pascal) { + sprintf(tmp, "{$definec %s %s}\n", var, value ? value : "1"); + } else { + sprintf(tmp, "Option '-D|d' is not supported with this plugin"); + CLPReportError(CLPStr28_WarningText, tmp); + return 0; + } + + AddStringToHandle(&definesHandle, tmp); + return 1; +} + +int Opt_UndefineSymbol(const char *opt, void *, const char *arg, int flags) { + char tmp[300]; + + if (pTool->LANG == Lang_C_CPP || pTool->LANG == CWFOURCHAR('A','s','m',' ')) { + sprintf(tmp, "#undef %s\n", arg); + } else if (pTool->LANG == Lang_Pascal) { + sprintf(tmp, "{$undefc %s}\n", arg); + } else { + sprintf(tmp, "Option -%s is not supported with this plugin", opt); + CLPReportError(CLPStr28_WarningText, tmp); + return 0; + } + + AddStringToHandle(&definesHandle, tmp); + return 1; +} + +int Opt_AddPrefixFile(const char *opt, void *handle, const char *filename, int flags) { + char tmp[300]; + + handle = !handle ? &definesHandle : handle; + if (!filename[0]) + return 1; + + if (pTool->LANG == Lang_C_CPP || pTool->LANG == CWFOURCHAR('A','s','m',' ')) { + if (filename[0] == '<' && filename[strlen(filename) - 1] == '>') { + snprintf(tmp, sizeof(tmp), "#include %s\n", filename); + } else { + snprintf(tmp, sizeof(tmp), "#include \"%s\"\n", filename); + } + } else if (pTool->LANG == Lang_Pascal) { + snprintf(tmp, sizeof(tmp), "{$I+}\n{$I %s}\n{$I-}\n", filename); + } else { + sprintf(tmp, "Option -%s is not supported with this plugin", opt); + CLPReportError(CLPStr28_WarningText, tmp); + return 0; + } + + AddStringToHandle((Handle *) handle, tmp); + return 1; +} + +int Opt_PragmaTrueFalse(const char *, void *flag, const char *, int flags) { + if (flags & PARAMPARSEFLAGS_8) + *((unsigned char *) flag) = PR_OFF; + else + *((unsigned char *) flag) = PR_ON; + return 1; +} + +int Opt_PragmaFalseTrue(const char *, void *flag, const char *, int flags) { + if (flags & PARAMPARSEFLAGS_8) + *((unsigned char *) flag) = PR_ON; + else + *((unsigned char *) flag) = PR_OFF; + return 1; +} + +int Opt_PragmaOnOff(const char *, void *flag, const char *arg) { + if (!arg) { + CLPReportError(CLPStr34_ArgumentsExpected); + return 0; + } + + if (!ustrcmp(arg, "on")) { + *((unsigned char *) flag) = PR_ON; + } else if (!ustrcmp(arg, "off")) { + *((unsigned char *) flag) = PR_OFF; + } else { + CLPReportError(CLPStr12, arg); + return 0; + } + + return 1; +} + +int Opt_PragmaOffOn(const char *, void *flag, const char *arg) { + if (!arg) { + CLPReportError(CLPStr34_ArgumentsExpected); + return 0; + } + + if (!ustrcmp(arg, "on")) { + *((unsigned char *) flag) = PR_OFF; + } else if (!ustrcmp(arg, "off")) { + *((unsigned char *) flag) = PR_ON; + } else { + CLPReportError(CLPStr12, arg); + return 0; + } + + return 1; +} + +int SetupPragmas(const Pragma *pragmas) { + const char *set; + char on; + char off; + char tmp[300]; + + while (pragmas->pragma) { + if (pragmas->flags == PRAGMA_FLAGS_0 || pragmas->flags == PRAGMA_FLAGS_1) { + set = 0; + on = !(pragmas->flags == PRAGMA_FLAGS_1) ? PR_ON : PR_OFF; + off = !(pragmas->flags == PRAGMA_FLAGS_1) ? PR_OFF : PR_ON; + if (*((char *)pragmas->value) == on) + set = "on"; + else if (*((char *)pragmas->value) == off) + set = "off"; + else if (*((char *)pragmas->value) == PR_AUTO) + set = "auto"; + else if (*((char *)pragmas->value) == PR_RESET) + set = "reset"; + else + OS_ASSERT(186, *((char *)pragmas->value) == PR_UNSET); + + if (set) { + snprintf(tmp, sizeof(tmp), "#pragma %s %s\n", pragmas->pragma, set); + AddStringToHandle(&definesHandle, tmp); + } + } else { + OS_ASSERT(195, !"Can't handle pragma"); + } + pragmas++; + } + + return 1; +} diff --git a/command_line/C++_Parser/Src/Library/ParserHelpers.c b/command_line/C++_Parser/Src/Library/ParserHelpers.c new file mode 100644 index 0000000..4cb793e --- /dev/null +++ b/command_line/C++_Parser/Src/Library/ParserHelpers.c @@ -0,0 +1,535 @@ +#include "parser.h" +#include "cmdline.h" +#include <errno.h> + +SInt16 lastStage; +Boolean dashIMinusMovesPaths; +Boolean usedDashIMinus; +Boolean namingSysPaths; +static char STSbuf[256]; + +int FindFileInPath(const char *filename, OSSpec *fss) { + CWFileInfo fi; + CWResult result; + + fi.fullsearch = 1; + fi.dependencyType = 0; + fi.suppressload = 1; + fi.isdependentoffile = kCurrentCompiledFile; + + result = CWFindAndLoadFile(parseopts.context, filename, &fi); + if (!result) { + OS_FSSpec_To_OSSpec(&fi.filespec, fss); + return 1; + } else { + return 0; + } +} + +char *GetEnvVar(const char *name, Boolean warn, const char **match) { + const char *nptr; + const char *last; + char *ret; + + nptr = name; + last = name; + while (*nptr) { + ret = getenv(nptr); + if (ret) { + if (match) + *match = nptr; + return ret; + } + last = nptr; + nptr = &nptr[1 + strlen(nptr)]; + } + + if (warn) + CLPReportWarning(CLPStr52, last); + *match = 0; + return 0; +} + +static Boolean MatchesExtension(const char *list, const char *filename) { + char *fn; + const char *eptr; + const char *ptr; + + fn = OS_GetFileNamePtr((char *) filename); + eptr = strrchr(fn, '.'); + if (!eptr) + return 0; + if (!list) + return 1; + + ptr = eptr; + while (*list) { + if (*list == '|' && !*ptr) + return 1; + + if (my_tolower(*list) == my_tolower(*ptr)) { + list++; + ptr++; + continue; + } + + while (*list && *list != '|') + list++; + if (*list) + list++; + ptr = eptr; + } + + return !*list && !*ptr; +} + +int Opt_AddAccessPath(const char *opt, void *var, const char *arg, int flags) { + OSPathSpec spec; + int err; + + arg = arg ? arg : opt; + if (!arg) + return 0; + if (!arg[0]) + return 1; + + if (strlen(arg) >= 256) { + CLPReportError(CLPStr13, arg + strlen(arg) - 32, 256); + return 0; + } + + err = OS_MakePathSpec(0, arg, &spec); + if (err == ENOENT || err == ENOENT) { + CLPReportWarning(CLPStr45, arg); + return 1; + } else if (err != 0) { + CLPOSAlert(CLPStr45, err, arg); + return 1; + } + + // this 'if' gets optimised unnecessarily + if (!AddAccessPath(&spec, namingSysPaths, 0, var != NULL)) + return 0; + else + return 1; +} + +int Opt_AddFrameworkPath(const char *opt, void *var, const char *arg, int flags) { + OSPathSpec spec; + int err; + + arg = arg ? arg : opt; + if (!arg) + return 0; + if (!arg[0]) + return 1; + + if (strlen(arg) >= 256) { + CLPReportError(CLPStr13, arg + strlen(arg) - 32, 256); + return 0; + } + + err = OS_MakePathSpec(0, arg, &spec); + if (err == ENOENT || err == ENOENT) { + CLPReportWarning(CLPStr45, arg); + return 1; + } else if (err != 0) { + CLPOSAlert(CLPStr45, err, arg); + return 1; + } else { + Frameworks_AddPath(&spec); + return 1; + } +} + +int Opt_AddFramework(const char *opt, void *var, const char *arg, int flags) { + if (!Frameworks_AddFramework(arg ? arg : opt, 0, 0)) + return 0; + else + return 1; +} + +void ListParseMessage(void (*errprint)(const char *, va_list), const char *envvar, SInt16 id, ...) { + char buf[1024]; + va_list ap; + + if (envvar && envvar[0]) + sprintf(buf, "In environment variable '%s':\n", envvar); + else + buf[0] = 0; + + CLPGetErrorString(id, buf + strlen(buf)); + va_start(ap, id); + errprint(buf, ap); + va_end(ap); +} + +int AddAccessPathList(const char *list, char sep1, char sep2, int source, char *text, Boolean system, SInt32 position, Boolean recursive) { + char tmp[256]; + Boolean recurse; + OSPathSpec spec; + int err; + short type; + char *ptr; + + type = (Boolean) ((system == 1) ? 1 : 0) | (!source ? 0 : 2); + recurse = (list[0] == '+'); + if (recurse) + ++list; + + if (!strchr(list, sep1)) + sep1 = sep2; + + while (*list) { + ptr = tmp; + while (*list && *list != sep1 && (ptr + 1) < &tmp[256]) { + *(ptr++) = *(list++); + } + *ptr = 0; + + if ((ptr + 1) >= &tmp[256]) { + ListParseMessage( + CLPReportError_V, + (source == 1) ? text : NULL, + CLPStr9, + tmp, + tmp + strlen(tmp) - 16, + 256); + return 0; + } + + err = OS_MakePathSpec(0, tmp, &spec); + if (err) { + ListParseMessage( + CLPReportWarning_V, + (source == 1) ? text : NULL, + CLPStr45, + tmp); + } else { + AddAccessPath(&spec, type, position, recurse ^ recursive); + } + + if (*list) + ++list; + recurse = *list == '+'; + if (recurse) + ++list; + } + + return 1; +} + +int Opt_FindAndAddFile(const char *opt, void *var, const char *arg, int flags) { + OSSpec spec; + int err; + Boolean isfile; + + arg = arg ? arg : opt; + if (!arg) + return 0; + if (!*arg) + return 1; + + parseopts.userSpecifiedFiles++; + err = OS_MakeSpec(arg, &spec, &isfile); + if (!err) + err = OS_Status(&spec); + + if (!err && !isfile) { + CLPReportError(CLPStr47, arg); + parseopts.unusedFiles++; + return 0; + } else if (err && err != ENOENT) { + CLPOSAlert(CLPStr44, err, arg); + parseopts.unusedFiles++; + return 0; + } else if (err && parseopts.alwaysUsePaths) { + err = FindFileInPath(arg, &spec) ? 0 : ENOENT; + } + + if (err) { + CLPReportError(CLPStr44, arg); + parseopts.unusedFiles++; + return 0; + } + + if (var && !MatchesExtension((const char *) var, arg)) + CLPReportWarning(CLPStr76, arg, var); + + if (!AddFileToProject(&spec, lastStage, parseopts.lastoutputname, 1, -1)) { + parseopts.unusedFiles++; + return 0; + } else { + parseopts.lastoutputname[0] = 0; + return 1; + } +} + +int Opt_FindAndAddFileRef(const char *opt, void *var, const char *arg) { + OSSpec spec; + int err; + Boolean isfile; + + arg = arg ? arg : opt; + if (!arg) + return 0; + if (!*arg) + return 1; + + parseopts.userSpecifiedFiles++; + if (var && !MatchesExtension((const char *) var, arg)) + CLPReportWarning(CLPStr76, arg, var); + + err = OS_MakeSpec(arg, &spec, &isfile); + if (!err) + err = OS_Status(&spec); + + if (!err && !isfile) { + CLPReportError(CLPStr47, arg); + parseopts.unusedFiles++; + return 0; + } else if (err && parseopts.alwaysUsePaths) { + err = FindFileInPath(arg, &spec) ? 0 : ENOENT; + } + + if (!AddFileToProject(&spec, 0, 0, err == 0, -1)) { + parseopts.unusedFiles++; + return 0; + } else { + return AddAccessPath(&spec.path, 1, -1, 0) != 0; + } +} + +int Opt_AddUnixLibraryFile(const char *opt, void *var, const char *name) { + OSSpec spec; + Boolean failed; + const char *eptr; + const char *eend; + char tmpname[64]; + + if (strlen(name) >= 56) { + CLPReportError(CLPStr13, name + strlen(name) - 32, 64); + return 0; + } + + failed = 1; + if (!var) + var = ".lib|.a"; + + eptr = (const char *) var; + while (eptr && *eptr) { + eend = eptr; + while (*eend && *eend != '|') + ++eend; + + sprintf(tmpname, "lib%s%*.*s", name, eend - eptr, eend - eptr, eptr); + if (FindFileInPath(tmpname, &spec)) { + failed = 0; + break; + } + + if (*eend) + eptr = eend + 1; + else + eptr = eend; + } + + if (failed) { + failed = !FindFileInPath(name, &spec); + if (failed) + CLPReportError(CLPStr49, name, var, name); + } + + if (!failed) { + if (!AddFileToProject(&spec, 0, 0, 1, -1)) { + parseopts.unusedFiles++; + failed = 1; + } + } + + return !failed; +} + +int AddFileList(const char *list, char sep1, char sep2, int source, char *text, SInt32 position) { + char tmp[256]; + OSSpec spec; + char *ptr; + + if (!strchr(list, sep1)) + sep1 = sep2; + + while (*list) { + ptr = tmp; + while (*list && *list != sep1 && (ptr + 1) < &tmp[256]) { + *(ptr++) = *(list++); + } + *ptr = 0; + + if ((ptr + 1) >= &tmp[256]) { + ListParseMessage( + CLPReportError_V, + (source == 1) ? text : 0, + CLPStr9, + tmp, + tmp + strlen(tmp) - 16, + 256 + ); + return 0; + } + + if (!FindFileInPath(tmp, &spec)) { + if (OS_IsDir(&spec)) { + ListParseMessage( + CLPReportError_V, + (source == 1) ? text : 0, + CLPStr16, + tmp + ); + } else { + ListParseMessage( + CLPReportWarning_V, + (source == 1) ? text : 0, + CLPStr44, + tmp + ); + } + } else { + AddFileToProject(&spec, 0, 0, 1, position); + } + + if (*list) + ++list; + } + + return 1; +} + +int IsFileInOutputDirectory(const OSSpec *file) { + OSPathSpec outdir; + GetOutputFileDirectory(&outdir); + return OS_EqualPathSpec(&outdir, &file->path); +} + +void GetCFileNameInOutputDirectory(const char *input, char *name, int maxlen) { + char filename[64]; + OSSpec spec; + int err; + + err = OS_MakeFileSpec(input, &spec); + if (err) { + CLPOSAlert(CLPStr64, err, input); + name[0] = 0; + return; + } + + if (!IsFileInOutputDirectory(&spec)) { + CLPReportWarning(CLPStr61, OS_SpecToStringRelative(&spec, 0, STSbuf, sizeof(STSbuf))); + } + + OS_NameSpecToString(&spec.name, filename, 256); + if (strlen(filename) >= maxlen) { + CLPReportWarning(CLPStr65, filename, maxlen - 1); + filename[maxlen - 1] = 0; + } + + strcpy(name, filename); +} + +void GetPFileNameInOutputDirectory(const char *input, unsigned char *name, int len) { + GetCFileNameInOutputDirectory(input, (char *) name, len); + c2pstr((char *) name); +} + +void AddStringLenToHandle(Handle *h, const char *str, int len) { + SInt32 old; + + if (!*h) { + if ((*h = NewHandle(len + 1))) { + HLock(*h); + memcpy(**h, str, len); + (**h)[len] = 0; + HUnlock(*h); + } else { + exit(-23); + } + } else { + old = GetHandleSize(*h) - 1; + SetHandleSize(*h, old + len + 1); + if (MemError() == noErr) { + HLock(*h); + memcpy(**h + old, str, len); + (**h)[old + len] = 0; + HUnlock(*h); + } else { + exit(-23); + } + } +} + +void AddStringToHandle(Handle *h, const char *str) { + AddStringLenToHandle(h, str, strlen(str)); +} + +int Opt_PrintVersion(const char *opt, void *var, const char *arg, int flags) { + ShowVersion(0); + return 1; +} + +void GetFirstSourceFilenameBase(char *buffer, char *defaul) { + int cnt; + OSSpec spec; + char compiler[32]; + int x; + char *ext; + + cnt = GetFileCount(); + for (x = 0; x < cnt; x++) { + if (GetFileInfo(x, &spec, compiler)) { + if (compiler[0]) { + if (!strstr(compiler, "Lib")) { + OS_NameSpecToString(&spec.name, buffer, 256); + ext = strrchr(buffer, '.'); + if (ext) + *ext = 0; + memmove(buffer, buffer, strlen(buffer) + 1); + return; + } + } + } + } + + strcpy(buffer, defaul); +} + +int Opt_SavePrefs(const char *opt, void *var, const char *arg, int flags) { + Parser_StorePanels(parseopts.context); + return 1; +} + +int ParseNumber(const char *arg, Boolean emit_error, SInt32 *ret, const char **endptr) { + char *end; + + if (arg[0] == '0' && (arg[1] == 'x' || arg[1] == 'X')) { + *ret = strtol(arg + 2, &end, 16); + } else if (arg[0] == '0') { + *ret = strtol(arg + 1, &end, 8); + } else { + *ret = strtol(arg, &end, 10); + } + + if (endptr) + *endptr = end; + + if (*end && emit_error) { + CLPReportError(CLPStr5, "", arg); + return 0; + } + + return 1; +} + +int Opt_MaybeMoveAccessPaths(const char *opt, void *var, const char *arg, int flags) { + if (dashIMinusMovesPaths && !usedDashIMinus) + MoveSystemPathsIntoUserList(); + return 1; +} diff --git a/command_line/C++_Parser/Src/Library/Projects.c b/command_line/C++_Parser/Src/Library/Projects.c new file mode 100644 index 0000000..dca9df2 --- /dev/null +++ b/command_line/C++_Parser/Src/Library/Projects.c @@ -0,0 +1,241 @@ +#include "parser.h" + +extern char STSbuf[256]; + +int GetFileCount(void) { + SInt32 num; + CWGetProjectFileCount(parseopts.context, &num); + return num; +} + +void SetFileOutputName(SInt32 position, SInt16 which, char *outfilename) { + CWResult result; + if (outfilename && outfilename[0]) { + result = CWParserSetFileOutputName(parseopts.context, position, which ? which : 1, outfilename); + if (result) { + failedCallback = "CWParserSetFileOutputName"; + longjmp(exit_plugin, result); + } + } +} + +int AddFileToProject(OSSpec *oss, SInt16 which, char *outfilename, Boolean exists, SInt32 position) { + CWFileSpec cws; + CWNewProjectEntryInfo pei; + CWResult result; + int err; + + err = OS_OSSpec_To_FSSpec(oss, &cws); + if (err) { + CLPOSAlert(44, err, OS_SpecToStringRelative(oss, 0, STSbuf, sizeof(STSbuf))); + return 0; + } + + if (position == -2) { + pei.position = 0; + } else if (position == -1) { + CWGetProjectFileCount(parseopts.context, &pei.position); + } else if (position == 0) { + pei.position = -1; + } else { + pei.position = position; + } + + pei.segment = parseopts.currentSegment; + pei.overlayGroup = parseopts.currentOverlayGroup; + pei.overlay = parseopts.currentOverlay; + pei.groupPath = NULL; + pei.mergeintooutput = parseopts.mergeIntoOutput; + pei.weakimport = parseopts.weakImport; + pei.initbefore = parseopts.initBefore; + result = CWAddProjectEntry(parseopts.context, &cws, exists == 0, &pei, &position); + if (result) { + failedCallback = "CWAddProjectEntry"; + longjmp(exit_plugin, result); + } + parseopts.initBefore = 0; + parseopts.weakImport = 0; + parseopts.mergeIntoOutput = 0; + SetFileOutputName(position, which, outfilename); + return 1; +} + +Boolean GetFileInfo(SInt32 position, OSSpec *spec, char *plugin) { + CWProjectFileInfo pfi; + if (CWGetFileInfo(parseopts.context, position, 1, &pfi)) + return 0; + + OS_FSSpec_To_OSSpec(&pfi.filespec, spec); + strncpy(plugin, pfi.dropinname, 32); + plugin[31] = 0; + return 1; +} + +int AddAccessPath(OSPathSpec *oss, SInt16 type, SInt32 position, Boolean recursive) { + CWNewAccessPathInfo api; + CWResult result; + OSSpec spec; + int err; + CWAccessPathListInfo apli; + + if ((err = OS_MakeSpecWithPath(oss, NULL, 0, &spec)) || (err = OS_OSSpec_To_FSSpec(&spec, &api.pathSpec))) { + CLPOSAlert(45, err, OS_PathSpecToString(&spec.path, STSbuf, sizeof(STSbuf))); + return 0; + } + + if (position == -2) { + api.position = 0; + } else if (position == -1 || position == 0) { + api.position = -1; + } else if (position == -1) { + result = CWGetAccessPathListInfo(parseopts.context, &apli); + if (result) { + failedCallback = "CWGetAccessPathListInfo"; + longjmp(exit_plugin, result); + } + if ((type & 1) == 1) { + api.position = apli.systemPathCount; + } else { + api.position = apli.userPathCount; + } + } else { + api.position = position; + } + + api.type = (type & 1) ? cwSystemPath : cwUserPath; + api.type = api.type | (CWAccessPathType) ((type & 2) ? cwAccessPathTypeFlag2 : 0); + api.recursive = recursive; + + result = CWParserAddAccessPath(parseopts.context, &api); + if (result) { + failedCallback = "CWParserAddAccessPath"; + longjmp(exit_plugin, result); + } + + return 1; +} + +int MoveSystemPathsIntoUserList(void) { + CWResult result = CWParserSwapAccessPaths(parseopts.context); + return result == cwNoErr; +} + +void AddVirtualFile(const char *filename, Handle *text) { + CWResult result; + CWMemHandle mh; + + if (*text) { + CWSecretAttachHandle(parseopts.context, *text, &mh); + result = CWParserCreateVirtualFile(parseopts.context, filename, mh); + if (result) { + failedCallback = "CWParserCreateVirtualFile"; + longjmp(exit_plugin, result); + } + DisposeHandle(*text); + *text = NULL; + } +} + +void GetOutputFileDirectory(OSPathSpec *dir) { + CWResult result; + CWFileSpec idefss; + OSSpec spec; + + result = CWGetOutputFileDirectory(parseopts.context, &idefss); + if (result) { + failedCallback = "CWGetOutputFileDirectory"; + longjmp(exit_plugin, result); + } + + OS_FSSpec_To_OSSpec(&idefss, &spec); + *dir = spec.path; +} + +void SetOutputFileDirectory(OSPathSpec *dir) { + CWResult result; + CWFileSpec idefss; + OSSpec spec; + + OS_MakeSpecWithPath(dir, NULL, 0, &spec); + OS_OSSpec_To_FSSpec(&spec, &idefss); + + result = CWParserSetOutputFileDirectory(parseopts.context, &idefss); + if (result) { + failedCallback = "CWParserSetOutputFileDirectory"; + longjmp(exit_plugin, result); + } +} + +void AddOverlayGroup(const char *name, CWAddr64 *addr, SInt32 *groupnum, SInt32 *overlaynum) { + CWResult result; + + *overlaynum = -1; + result = CWParserAddOverlay1Group(parseopts.context, name, addr, groupnum); + if (result) { + if (result == cwErrInvalidCallback) { + CLPReportError(72); + } else { + failedCallback = "CWParserAddOverlay1Group"; + longjmp(exit_plugin, result); + } + } +} + +void AddOverlay(SInt32 groupnum, const char *name, SInt32 *overlaynum) { + CWResult result; + + result = CWParserAddOverlay1(parseopts.context, name, groupnum, overlaynum); + if (result) { + if (result == cwErrInvalidCallback) { + CLPReportError(72); + } else { + failedCallback = "CWParserAddOverlay1"; + longjmp(exit_plugin, result); + } + } +} + +void AddSegment(const char *name, SInt16 attrs, SInt32 *segmentnum) { + CWResult result; + + result = CWParserAddSegment(parseopts.context, name, attrs, segmentnum); + if (result) { + if (result == cwErrInvalidCallback) { + CLPReportError(73); + } else { + failedCallback = "CWParserAddSegment"; + longjmp(exit_plugin, result); + } + } +} + +void ChangeSegment(SInt32 segmentnum, const char *name, SInt16 attrs) { + CWResult result; + + result = CWParserSetSegment(parseopts.context, segmentnum, name, attrs); + if (result) { + if (result == cwErrInvalidCallback) { + CLPReportError(73); + } else { + failedCallback = "CWParserSetSegment"; + longjmp(exit_plugin, result); + } + } +} + +int GetSegment(SInt32 segmentnum, char *name, SInt16 *attrs) { + CWResult result; + CWProjectSegmentInfo psi; + + result = CWGetSegmentInfo(parseopts.context, segmentnum, &psi); + if (result) { + if (result == cwErrInvalidCallback) { + CLPReportError(73); + } + return 0; + } + + strcpy(name, psi.name); + *attrs = psi.attributes; + return 1; +} diff --git a/command_line/C++_Parser/Src/Library/StaticParserGlue.c b/command_line/C++_Parser/Src/Library/StaticParserGlue.c new file mode 100644 index 0000000..7a44487 --- /dev/null +++ b/command_line/C++_Parser/Src/Library/StaticParserGlue.c @@ -0,0 +1,29 @@ +#include "parser.h" +#include "cmdline.h" + +static BasePluginCallbacks cb = { + parser_main, + CWParser_GetDropInFlags, + CWParser_GetDisplayName, + CWParser_GetDropInName, + CWParser_GetPanelList, + NULL, + NULL, + CWParser_GetVersionInfo, + NULL +}; + +static ParserPluginCallbacks pr_cb = { + Parser_SupportsPlugin, + Parser_SupportsPanels +}; + +int RegisterStaticParserPlugins(void) { + return RegisterStaticParserPlugin(&cb, &pr_cb); +} + +#include "ParserErrors.r" + +int RegisterStaticParserResources(void) { + return RegisterResource("Parser Strings", 12010, STR12010); +} diff --git a/command_line/C++_Parser/Src/Library/StdTargetWarningHelpers-cc.c b/command_line/C++_Parser/Src/Library/StdTargetWarningHelpers-cc.c new file mode 100644 index 0000000..c1f378d --- /dev/null +++ b/command_line/C++_Parser/Src/Library/StdTargetWarningHelpers-cc.c @@ -0,0 +1,81 @@ +#include "parser.h" + +PExtraWarningC pExtraWarningC = {0}; +Pragma warningPragmas[] = { + &pExtraWarningC.warn_largeargs, "warn_largeargs", 0, + &pExtraWarningC.warn_padding, "warn_padding", 0, + &pExtraWarningC.warn_resultnotused, "warn_resultnotused", 0, + &pExtraWarningC.warn_ptr_int_conv, "warn_ptr_int_conv", 0, + &pExtraWarningC.warn_no_side_effect, "warn_no_side_effect", 0, + 0, 0, 0 +}; + +int TargetSetWarningFlags(short val, Boolean set) { + switch (val) { + case 'Ip': pWarningC.warn_illpragma = set; break; + case 'Ed': pWarningC.warn_emptydecl = set; break; + case 'Pu': pWarningC.warn_possunwant = set; break; + case 'Uv': pWarningC.warn_unusedvar = set; break; + case 'Ua': pWarningC.warn_unusedarg = set; break; + case 'Ec': pWarningC.warn_extracomma = set; break; + case 'Pd': pWarningC.pedantic = set; break; + case 'Hv': pWarningC.warn_hidevirtual = set; break; + case 'Ic': pWarningC.warn_implicitconv = set; break; + case 'Ni': pWarningC.warn_notinlined = set; break; + case 'Sc': pWarningC.warn_structclass = set; break; + case 'Pa': pExtraWarningC.warn_padding = set ? PR_ON : PR_OFF; break; + case 'Nu': pExtraWarningC.warn_resultnotused = set ? PR_ON : PR_OFF; break; + case 'Se': pExtraWarningC.warn_no_side_effect = set ? PR_ON : PR_OFF; break; + case 'PI': pExtraWarningC.warn_ptr_int_conv = set ? PR_ON : PR_OFF; break; + case 'La': pExtraWarningC.warn_largeargs = set ? PR_ON : PR_OFF; break; + case 'We': pWarningC.warningerrors = set; break; + case 'Cp': pFrontEndC.checkprotos = set; break; + default: return 0; + } + + return 1; +} + +void TargetDisplayWarningOptions(Handle txt) { + HPrintF(txt, "C language warning options:\n"); + + if (pWarningC.warn_illpragma) + HPrintF(txt, "\t- illegal pragmas\n"); + if (pWarningC.warn_emptydecl) + HPrintF(txt, "\t- empty declarations\n"); + if (pWarningC.warn_possunwant) + HPrintF(txt, "\t- possible unwanted effects\n"); + if (pWarningC.warn_unusedvar) + HPrintF(txt, "\t- unused variables\n"); + if (pWarningC.warn_unusedarg) + HPrintF(txt, "\t- unused arguments\n"); + if (pWarningC.warn_extracomma) + HPrintF(txt, "\t- extra commas\n"); + if (pWarningC.pedantic) + HPrintF(txt, "\t- pedantic\n"); + if (pWarningC.warn_hidevirtual) + HPrintF(txt, "\t- hidden virtual functions\n"); + if (pWarningC.warn_implicitconv) + HPrintF(txt, "\t- implicit conversions\n"); + if (pWarningC.warn_notinlined) + HPrintF(txt, "\t- 'inline' not performed\n"); + if (pWarningC.warn_structclass) + HPrintF(txt, "\t- struct/class conflict\n"); + if (pExtraWarningC.warn_largeargs == 1) + HPrintF(txt, "\t- large args passed to unprototyped functions\n"); + if (pExtraWarningC.warn_padding == 1) + HPrintF(txt, "\t- padding added between struct members\n"); + if (pExtraWarningC.warn_resultnotused == 1) + HPrintF(txt, "\t- result of non-void function call not used\n"); + if (pExtraWarningC.warn_no_side_effect == 1) + HPrintF(txt, "\t- use of expressions as statements without side effects\n"); + if (pExtraWarningC.warn_ptr_int_conv == 1) + HPrintF(txt, "\t- implicit integer/pointer conversions\n"); + if (pFrontEndC.checkprotos) + HPrintF(txt, "\t- checking prototypes\n"); + + if (pWarningC.warningerrors) + HPrintF(txt, "\t- warnings are errors\n"); + else + HPrintF(txt, "\t- warnings are not errors\n"); +} diff --git a/command_line/C++_Parser/Src/Library/Targets.c b/command_line/C++_Parser/Src/Library/Targets.c new file mode 100644 index 0000000..378b9d7 --- /dev/null +++ b/command_line/C++_Parser/Src/Library/Targets.c @@ -0,0 +1,65 @@ +#include "parser.h" + +ParserTool *pTool; + +int SetParserToolInfo(ParserTool *tool) { + pTool = tool; + + OS_ASSERT(16, pTool->toolInfo && (parseopts.toolVersion || pTool->copyright)); + + return 1; +} + +Boolean ParserToolMatchesPlugin(OSType type, OSType lang, OSType cpu, OSType os) { + if (!pTool) { + CLPFatalError("No options loaded for command line\n"); + return 0; + } + + if ( + (type == CWDROPINANYTYPE || pTool->TYPE == CWDROPINANYTYPE || pTool->TYPE == type) && + (lang == Lang_Any || pTool->LANG == Lang_Any || pTool->LANG == lang) && + (cpu == targetCPUAny || pTool->CPU == targetCPUAny || pTool->CPU == cpu) && + (os == targetOSAny || pTool->OS == targetOSAny || pTool->OS == os) + ) + { + return 1; + } else { + return 0; + } +} + +Boolean ParserToolHandlesPanels(int numPanels, const char **panelNames) { + int idx; + int scan; + + if (!pTool) + CLPFatalError("No options loaded for command line\n"); + + for (idx = 0; idx < numPanels; idx++) { + for (scan = 0; scan < pTool->numPrefPanels; scan++) { + if (!ustrcmp(pTool->prefPanels[scan], panelNames[idx])) + break; + } + + if (scan >= pTool->numPrefPanels) + break; + } + + if (idx >= numPanels) + return 1; + else + return 0; +} + +Boolean SetupParserToolOptions(void) { + int idx; + + Options_Init(); + for (idx = 0; idx < pTool->numOptionLists; idx++) { + Options_AddList(pTool->optionLists[idx]); + } + Options_SortOptions(); + + return 1; +} diff --git a/command_line/C++_Parser/Src/Library/ToolHelpers-cc.c b/command_line/C++_Parser/Src/Library/ToolHelpers-cc.c new file mode 100644 index 0000000..b58f188 --- /dev/null +++ b/command_line/C++_Parser/Src/Library/ToolHelpers-cc.c @@ -0,0 +1,36 @@ +#include "parser.h" +#include "cmdline.h" + +int Opt_DummyLinkerRoutine(const char *opt, void *, const char *, int) { + CLPFatalError("Calling linker option '%s'\n", opt); + return 0; +} + +int Opt_DummyLinkerSettingRoutine(const char *var, const char *val) { + CLPFatalError("Calling linker settings option '%s'='%s'\n", var, val ? val : ""); + return 0; +} + +void FinishCompilerTool(void) { + SInt32 numfiles; + + if (parseopts.lastoutputname[0]) { + numfiles = GetFileCount(); + + if (pCmdLine.stages == CmdLineStageMask_Dp) { + strcpy(pCmdLineCompiler.outMakefile, parseopts.lastoutputname); + } else if (outputOrdering == OutputOrdering2) { + if (parseopts.possibleFiles > 0 || parseopts.userSpecifiedFiles > 0) + CLPReportError(41, parseopts.lastoutputname); + else + CLPReportError(42, parseopts.lastoutputname); + } else { + SetFileOutputName(numfiles - 1, lastStage, parseopts.lastoutputname); + } + + parseopts.lastoutputname[0] = 0; + } + + if (setOutputDirectory) + pCmdLineCompiler.relPathInOutputDir = 0; +} diff --git a/command_line/C++_Parser/Src/Library/ToolHelpers.c b/command_line/C++_Parser/Src/Library/ToolHelpers.c new file mode 100644 index 0000000..e872546 --- /dev/null +++ b/command_line/C++_Parser/Src/Library/ToolHelpers.c @@ -0,0 +1,289 @@ +#include "parser.h" +#include "cmdline.h" +#include <errno.h> + +extern char STSbuf[256]; + +static Boolean setStage; +char linkerOutputFilename[256]; +Boolean setLinkerOutputFilename; +Boolean setOutputDirectory; +SInt16 outputOrdering; + +int Opt_HandleOutputName(const char *opt, void *, const char *filename, int flags) { + OSSpec spec; + int err; + SInt32 result; + Boolean isfile; + + if (!filename) + filename = opt; + + if ((pCmdLine.state == OptsCmdLineState_3 || (pCmdLine.state == OptsCmdLineState_0 && pTool->TYPE == CWDROPINLINKERTYPE)) && pCmdLine.toDisk != 4) { + if (setLinkerOutputFilename) { + CLPReportError(CLPStr41, filename); + return 0; + } + setLinkerOutputFilename = 1; + if (pTool->TYPE == CWDROPINCOMPILERTYPE) { + strncpy(linkerOutputFilename, filename, 256); + } else { + OSSpec spec; + int err; + Boolean isfile; + err = OS_MakeSpec(filename, &spec, &isfile); + if (err) { + CLPOSAlert(CLPStr64, err, filename); + return 0; + } + if (isfile) + OS_NameSpecToString(&spec.name, linkerOutputFilename, 256); + SetOutputFileDirectory(&spec.path); + } + return 1; + } else { + err = OS_MakeSpec(filename, &spec, &isfile); + if (err) { + CLPOSAlert(CLPStr64, err, filename); + return 0; + } + + if (!err && !isfile) { + FSSpec ofd; + if (setOutputDirectory) { + CLPReportError(CLPStr59, filename); + return 0; + } + setOutputDirectory = 1; + + OS_OSSpec_To_FSSpec(&spec, &ofd); + result = CWParserSetOutputFileDirectory(parseopts.context, &ofd); + if (result) { + failedCallback = "CWParserSetOutputFileDirectory"; + longjmp(exit_plugin, result); + } + return 1; + } else { + SInt32 index; + CWProjectFileInfo pfi; + if (parseopts.lastoutputname[0]) { + CLPReportError(CLPStr41, filename); + return 0; + } + strncpy(parseopts.lastoutputname, filename, 256); + if (pCmdLine.stages == CmdLineStageMask_Dp) + return 1; + + if (outputOrdering == OutputOrdering0 || outputOrdering == OutputOrdering1) { + CWGetProjectFileCount(parseopts.context, &index); + while (index-- > 0) { + if (!CWGetFileInfo(parseopts.context, index, 0, &pfi) && pfi.filetype == CWFOURCHAR('T','E','X','T')) { + outputOrdering = OutputOrdering1; + break; + } + } + + if (index <= 0) { + CWGetProjectFileCount(parseopts.context, &index); + if (index > 0) + outputOrdering = OutputOrdering1; + --index; + } + + if (outputOrdering == OutputOrdering0) { + outputOrdering = OutputOrdering2; + return 1; + } + + SetFileOutputName(index, lastStage, parseopts.lastoutputname); + parseopts.lastoutputname[0] = 0; + } + + return 1; + } + } +} + +int ValidateToolState(Boolean mustHaveFiles) { + if (parseopts.noOptions) { + pCmdLine.state = OptsCmdLineState_1; + ShowVersion(1); + return 1; + } + + if (parseopts.success) { + if (!parseopts.userSpecifiedFiles) { + if (!parseopts.hadAnyOutput) { + if (mustHaveFiles) { + CLPReportError(CLPStr70); + return 0; + } + } else { + if (mustHaveFiles) + pCmdLine.state = OptsCmdLineState_1; + return 1; + } + } else if (parseopts.unusedFiles > 0) { + CLPReportError(CLPStr69); + return 0; + } + } + + if (pCmdLine.state == OptsCmdLineState_0 || (parseopts.userSpecifiedFiles > 0 && pCmdLine.state == OptsCmdLineState_1)) + pCmdLine.state = OptsCmdLineState_3; + + if (!setStage) { + pCmdLine.stages = CmdLineStageMask_Cg; + if (pCmdLine.state == OptsCmdLineState_2) + pCmdLine.toDisk |= 2; + } + + if (pCmdLine.state == OptsCmdLineState_3 && !(pCmdLine.stages & CmdLineStageMask_Cg)) + pCmdLine.state = OptsCmdLineState_2; + + return 1; +} + +void ToolReportMessage(SInt16 errid, SInt16 type, va_list va) { + char str[256]; + char buf[1024]; + + GetIndString((StringPtr) str, 13000, errid); + p2cstr((StringPtr) str); + vsprintf(buf, str, va); + CWReportMessage(parseopts.context, 0, buf, 0, type, 0); +} + +void ToolReportWarning(SInt16 id, ...) { + va_list va; + va_start(va, id); + ToolReportMessage(id, messagetypeWarning, va); + va_end(va); +} + +void ToolReportError(SInt16 id, ...) { + va_list va; + va_start(va, id); + ToolReportMessage(id, messagetypeError, va); + va_end(va); + parseopts.hadErrors = 1; +} + +void ToolReportOSError(SInt16 id, int err, ...) { + char str[256]; + char buf[1024]; + va_list va; + + GetIndString((StringPtr) str, 13000, id); + p2cstr((StringPtr) str); + va_start(va, err); + vsprintf(buf, str, va); + va_end(va); + CWAlert(parseopts.context, buf, OS_GetErrText(err), 0, 0); +} + +void ToolReportInfo(SInt16 id, ...) { + va_list va; + va_start(va, id); + ToolReportMessage(id, messagetypeInfo, va); + va_end(va); +} + +int Opt_DoNotLink(const char *opt, void *var, const char *arg) { + if (pCmdLine.state == OptsCmdLineState_3 || pCmdLine.state == OptsCmdLineState_0 || pCmdLine.state == OptsCmdLineState_1) + pCmdLine.state = OptsCmdLineState_2; + return 1; +} + +int Opt_IncreaseVerbosity(const char *opt, void *var, const char *arg, int flags) { + if (pCmdLine.verbose) + pCmdLine.verbose++; + else + pCmdLine.verbose = 2; + + Parser_StorePanels(parseopts.context); + return 1; +} + +int Opt_SetStage(const char *opt, void *str, const char *arg, int flags) { + unsigned char *ptr; + Boolean set; + Boolean no; + UInt16 flag; + + ptr = (unsigned char *) str; + // doesn't match - type issue with 'no' + no = (Boolean) ((flags & PARAMPARSEFLAGS_8) >> 3); + set = (Boolean) (no ^ 1); + + while (*ptr) { + if (*ptr == '+') { + set = !no; + } else if (*ptr == '-') { + set = no; + } else if (*ptr == '|') { + set = (Boolean) (no ^ 1); + } else { + flag = (ptr[0] << 8) | ptr[1]; + setStage = 1; + + switch (flag) { + case 'Cg': + if (set) + pCmdLine.stages |= CmdLineStageMask_Cg; + else + pCmdLine.stages &= ~CmdLineStageMask_Cg; + lastStage = CmdLineStage_Cg; + break; + case 'Ds': + if (set) + pCmdLine.stages |= CmdLineStageMask_Ds; + else + pCmdLine.stages &= ~CmdLineStageMask_Ds; + lastStage = CmdLineStage_Ds; + break; + case 'Pp': + if (set) + pCmdLine.stages |= CmdLineStageMask_Pp; + else + pCmdLine.stages &= ~CmdLineStageMask_Pp; + lastStage = CmdLineStage_Pp; + break; + case 'Dp': + if (set) + pCmdLine.stages |= CmdLineStageMask_Dp; + else + pCmdLine.stages &= ~CmdLineStageMask_Dp; + break; + default: + CLPFatalError("Bad stage settings in %s (%c%c)\n", str, ptr[0], ptr[1]); + } + + ++ptr; + } + + ++ptr; + } + + return 1; +} + +int Opt_RedirectStream(const char *opt, void *file, const char *filename) { + OSSpec spec; + int err; + FILE *nw; + + err = OS_MakeFileSpec(filename, &spec); + if (err) { + CLPReportError(CLPStr78, filename, OS_GetErrText(err)); + return 0; + } + + nw = freopen(OS_SpecToString(&spec, STSbuf, 256), "wt", (FILE *) file); + if (!nw) { + CLPReportError(CLPStr78, filename, strerror(errno)); + return 0; + } + + return 1; +} diff --git a/command_line/C++_Parser/Src/Library/Utils.c b/command_line/C++_Parser/Src/Library/Utils.c new file mode 100644 index 0000000..b627c4d --- /dev/null +++ b/command_line/C++_Parser/Src/Library/Utils.c @@ -0,0 +1,174 @@ +#include "parser.h" + +int my_tolower(char c) { + if (c >= 'A' && c <= 'Z') + return c | 0x20; + else + return c; +} + +int my_isdigit(char c) { + return (c >= '0' && c <= '9'); +} + +int my_isalpha(char c) { + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); +} + +int my_isalnum(char c) { + return my_isdigit(c) || my_isalpha(c); +} + +int my_isxdigit(char c) { + return my_isdigit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); +} + +char *Utils_SpellList(char *list, char *buffer, char opts) { + char *sptr; + char *eptr; + char *nptr; + char *bptr; + int pflen; + int npflen; + int undo; + char *neptr; + int cnt; + + undo = 0; + bptr = buffer; + sptr = list; + pflen = 0; + while (sptr) { + if ((opts & 1) && !pflen) + *(bptr++) = *MAINOPTCHAR; + + eptr = strchr(sptr, '|'); + if (!eptr) { + eptr = sptr + strlen(sptr); + nptr = 0; + } else if (eptr[1] == '|') { + nptr = 0; + } else { + nptr = eptr + 1; + } + + if (undo == 0 && !pflen) { + if (opts & 8) { + *(bptr++) = '['; + *(bptr++) = 'n'; + *(bptr++) = 'o'; + *(bptr++) = ']'; + } + if (opts & 0x20) { + *(bptr++) = '['; + *(bptr++) = 'n'; + *(bptr++) = 'o'; + *(bptr++) = '-'; + *(bptr++) = ']'; + } + } + + npflen = 0; + if (nptr) { + while (sptr < nptr && *nptr && *nptr != '|' && sptr[npflen] == nptr[npflen]) + npflen++; + + if (npflen) { + neptr = strchr(nptr, '|'); + if (!neptr) + neptr = nptr + strlen(nptr); + if ((neptr - nptr) < (eptr - sptr) || ((sptr[1] && sptr[1] != '|') ? (sptr[1] != nptr[1]) : 0)) + npflen = 0; + if (opts & 0x40) + npflen = 0; + } + } + + if (pflen) { + sptr += pflen; + while (sptr < eptr) { + *(bptr++) = *(sptr++); + } + if (npflen > pflen) { + *(bptr++) = '['; + undo++; + } + if (npflen < pflen) { + *(bptr++) = ']'; + undo--; + } + } else if (npflen) { + for (cnt = npflen; cnt > 0; cnt--) { + *(bptr++) = *(sptr++); + } + *(bptr++) = '['; + undo++; + } + + while (sptr < eptr) { + *(bptr++) = *(sptr++); + } + + if (opts & 0x10) { + *(bptr++) = '['; + *(bptr++) = '-'; + *(bptr++) = ']'; + } + if (opts & 0x40) { + *(bptr++) = '+'; + } + + sptr = nptr; + if (nptr && bptr[-1] != '[') { + if ((opts & 1) || (bptr[-1] == ']') || ((opts & 8) && !undo)) { + *(bptr++) = ' '; + *(bptr++) = '|'; + *(bptr++) = ' '; + } else { + *(bptr++) = '|'; + } + } + + opts &= ~0x40; + pflen = npflen; + } + + for (cnt = undo; cnt; cnt--) { + *(bptr++) = ']'; + } + + if (opts & 4) + bptr += sprintf(bptr, "=..."); + + *bptr = 0; + return bptr; +} + +int Utils_CompareOptionString(const char *a, const char *b, int cased, int sticky) { + const char *ae; + const char *be; + + for (ae = a; *ae && *ae != '|'; ae++) {} + for (be = b; *be && *be != '|'; be++) {} + + if (sticky && (be - b) < (ae - a)) + return 0; + + if (cased) { + while (a < ae && b < be) { + if (*a != *b) + break; + a++; + b++; + } + } else { + while (a < ae && b < be) { + if (my_tolower(*a) != my_tolower(*b)) + break; + a++; + b++; + } + } + + return (a == ae) && (sticky || b == be); +} |