summaryrefslogtreecommitdiff
path: root/command_line/C++_Parser/Src/Library
diff options
context:
space:
mode:
Diffstat (limited to 'command_line/C++_Parser/Src/Library')
-rw-r--r--command_line/C++_Parser/Src/Library/Arguments.c590
-rw-r--r--command_line/C++_Parser/Src/Library/Help.c561
-rw-r--r--command_line/C++_Parser/Src/Library/IO.c83
-rw-r--r--command_line/C++_Parser/Src/Library/OptimizerHelpers.c166
-rw-r--r--command_line/C++_Parser/Src/Library/Option.c1136
-rw-r--r--command_line/C++_Parser/Src/Library/Parameter.c1145
-rw-r--r--command_line/C++_Parser/Src/Library/ParserErrors.c119
-rw-r--r--command_line/C++_Parser/Src/Library/ParserFace.c298
-rw-r--r--command_line/C++_Parser/Src/Library/ParserHelpers-cc.c156
-rw-r--r--command_line/C++_Parser/Src/Library/ParserHelpers.c535
-rw-r--r--command_line/C++_Parser/Src/Library/Projects.c241
-rw-r--r--command_line/C++_Parser/Src/Library/StaticParserGlue.c29
-rw-r--r--command_line/C++_Parser/Src/Library/StdTargetWarningHelpers-cc.c81
-rw-r--r--command_line/C++_Parser/Src/Library/Targets.c65
-rw-r--r--command_line/C++_Parser/Src/Library/ToolHelpers-cc.c36
-rw-r--r--command_line/C++_Parser/Src/Library/ToolHelpers.c289
-rw-r--r--command_line/C++_Parser/Src/Library/Utils.c174
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);
+}