diff --git a/src/mmcmdl.c b/src/mmcmdl.c index d07d3476..46e3b3f8 100644 --- a/src/mmcmdl.c +++ b/src/mmcmdl.c @@ -1646,17 +1646,16 @@ static flag getFullArg(long arg, const char *cmdList1) { vstring_def(infoStr); vstring_def(errorLine); vstring_def(keyword); - vstring_def(cmdList); - let(&cmdList,cmdList1); /* In case cmdList1 gets deallocated when it comes + vstring_def(cmdList); + let(&cmdList, cmdList1); /* In case cmdList1 gets deallocated when it comes directly from a vstring function such as cat() */ - let(&errorLine, cat(g_commandPrompt,g_commandLine, NULL)); + let(&errorLine, cat(g_commandPrompt, g_commandLine, NULL)); /* Handle special case - integer expected */ if (cmdList[0] == '#') { - let(&defaultCmd, - seg(cmdList,instr(1,cmdList, "<"),instr(1,cmdList, ">"))); + let(&defaultCmd, seg(cmdList, instr(1, cmdList, "<"), instr(1, cmdList, ">"))); /* If the argument has not been entered, prompt the user for it */ if (g_rawArgs <= arg) { @@ -1666,10 +1665,10 @@ static flag getFullArg(long arg, const char *cmdList1) { if (g_rawArgs <= arg) bug(1103); g_queryMode = 1; - vstring argLine = cmdInput1(right(cmdList,3)); - let(&errorLine,right(cmdList,3)); + vstring argLine = cmdInput1(right(cmdList, 3)); + let(&errorLine, right(cmdList, 3)); if (argLine[0] == 0) { /* Use default argument */ - let(&argLine, seg(defaultCmd,2,len(defaultCmd) - 1)); + let(&argLine, seg(defaultCmd, 2, len(defaultCmd) - 1)); } let((vstring *)(&g_rawArgPntr[arg]), argLine); free_vstring(argLine); @@ -1679,17 +1678,16 @@ static flag getFullArg(long arg, const char *cmdList1) { /* Make sure that the argument is a non-negative integer */ vstring_def(tmpArg); - let(&tmpArg,g_rawArgPntr[arg]); + let(&tmpArg, g_rawArgPntr[arg]); if (tmpArg[0] == 0) { /* Use default argument */ /* (This code is needed in case of null string passed directly) */ - let(&tmpArg, seg(defaultCmd,2,len(defaultCmd) - 1)); + let(&tmpArg, seg(defaultCmd, 2, len(defaultCmd) - 1)); } vstring_def(tmpStr); let(&tmpStr, str(val(tmpArg))); let(&tmpStr, cat(string(len(tmpArg)-len(tmpStr),'0'), tmpStr, NULL)); if (strcmp(tmpStr, tmpArg)) { - printCommandError(errorLine, arg, - "?A number was expected here."); + printCommandError(errorLine, arg, "?A number was expected here."); ret = 0; } else { let(&keyword, str(val(tmpArg))); @@ -1706,14 +1704,13 @@ static flag getFullArg(long arg, const char *cmdList1) { /* '*' means any string, '&' means a file */ /* However, "|$<$>" also allows null string (no argument) */ if (cmdList[0] == '*' || cmdList[0] == '&') { - let(&defaultCmd, - seg(cmdList,instr(1,cmdList, "<"),instr(1,cmdList, ">"))); + let(&defaultCmd, seg(cmdList,instr(1, cmdList, "<"), instr(1, cmdList, ">"))); /* If the argument has not been entered, prompt the user for it */ if (g_rawArgs <= arg) { if (!strcmp(defaultCmd, "<$>")) { /* End of command acceptable */ /* Note: in this case, user will never be prompted for anything. */ - let(&keyword,chr(3)); + let(&keyword, chr(3)); goto getFullArg_ret; } g_rawArgs++; @@ -1735,16 +1732,16 @@ static flag getFullArg(long arg, const char *cmdList1) { } *******/ - let(&errorLine,right(cmdList,3)); + let(&errorLine, right(cmdList,3)); if (tmpArg[0] == 0) { /* Use default argument */ - let(&tmpArg, seg(defaultCmd,2,len(defaultCmd) - 1)); + let(&tmpArg, seg(defaultCmd, 2, len(defaultCmd) - 1)); } let((vstring *)(&g_rawArgPntr[arg]), tmpArg); g_rawArgNmbr[arg] = len(cmdList) - 1; /* Line position for error msgs */ free_vstring(tmpArg); } /* End of asking user for additional argument */ - let(&keyword,g_rawArgPntr[arg]); + let(&keyword, g_rawArgPntr[arg]); /* Convert abbreviations of FIRST, LAST, ALL to full keywords. The rest of the program works fine without doing this, @@ -1772,7 +1769,7 @@ static flag getFullArg(long arg, const char *cmdList1) { let(&tmpStr, cat(g_rootDirectory, keyword, NULL)); FILE *tmpFp = fopen(tmpStr, "r"); if (!tmpFp) { - let(&tmpStr, cat("?Sorry, couldn't open the file \"", tmpStr, "\".", NULL)); + let(&tmpStr, cat("?Sorry, couldn't open the file \"", tmpStr, "\".", NULL)); printCommandError(errorLine, arg, tmpStr); free_vstring(tmpStr); ret = 0; @@ -1792,8 +1789,8 @@ static flag getFullArg(long arg, const char *cmdList1) { while (1) { p = instr(p + 1, cat(cmdList, "|", NULL), "|"); if (!p) break; - pntrLet(&possCmd,pntrAddElement(possCmd)); - let((vstring *)(&possCmd[possCmds]),seg(cmdList,q+1,p-1)); + pntrLet(&possCmd, pntrAddElement(possCmd)); + let((vstring *)(&possCmd[possCmds]), seg(cmdList, q+1, p-1)); possCmds++; q = p; } @@ -1801,10 +1798,11 @@ static flag getFullArg(long arg, const char *cmdList1) { // free_vstring(defaultCmd); // Not needed because defaultCmd is already empty /* Get default argument, if any */ defaultCmd = possCmd[possCmds - 1]; /* re-use old allocation */ + if (!strcmp(defaultCmd, "<$>")) { let(&defaultCmd, ""); } - pntrLet(&possCmd,pntrLeft(possCmd,possCmds - 1)); + pntrLet(&possCmd, pntrLeft(possCmd, possCmds - 1)); possCmds--; } if (!strcmp(possCmd[possCmds - 1], "$")) { @@ -1857,9 +1855,9 @@ static flag getFullArg(long arg, const char *cmdList1) { print2("%s\n", tmpArg); } } - let(&errorLine,tmpStr); + let(&errorLine, tmpStr); if (tmpArg[0] == 0) { /* Use default argument */ - let(&tmpArg, seg(defaultCmd,2,len(defaultCmd) - 1)); + let(&tmpArg, seg(defaultCmd, 2, len(defaultCmd) - 1)); } if (strcmp(tmpArg, "nothing")) { @@ -1877,13 +1875,12 @@ static flag getFullArg(long arg, const char *cmdList1) { if (g_rawArgs <= arg) { /* No argument was specified, and "nothing" is a valid argument */ - let(&keyword,chr(3)); + let(&keyword, chr(3)); goto getFullArg_ret; } - vstring_def(tmpArg); - let(&tmpArg,edit(g_rawArgPntr[arg], 32)); /* Convert to upper case */ + let(&tmpArg, edit(g_rawArgPntr[arg], 32)); /* Convert to upper case */ long j = 0; long k = 0; long m = len(tmpArg); @@ -1913,14 +1910,14 @@ static flag getFullArg(long arg, const char *cmdList1) { let(&tmpStr, cat("?Expected ", infoStr, ".", NULL)); } else { if (k == 2) { - p = instr(1,tmpStr, ", "); - let(&tmpStr, cat(left(tmpStr,p-1), " or",right(tmpStr,p+1), NULL)); + p = instr(1, tmpStr, ", "); + let(&tmpStr, cat(left(tmpStr, p-1), " or", right(tmpStr, p+1), NULL)); } else { p = len(tmpStr) - 1; while (tmpStr[p] != ',') p--; - let(&tmpStr, cat(left(tmpStr,p+1), " or",right(tmpStr,p+2), NULL)); + let(&tmpStr, cat(left(tmpStr, p+1), " or", right(tmpStr, p+2), NULL)); } - let(&tmpStr, cat("?Ambiguous keyword - please specify ",tmpStr, ".", NULL)); + let(&tmpStr, cat("?Ambiguous keyword - please specify ", tmpStr, ".", NULL)); } printCommandError(errorLine, arg, tmpStr); free_vstring(tmpStr); @@ -1929,23 +1926,22 @@ static flag getFullArg(long arg, const char *cmdList1) { } free_vstring(tmpStr); - let(&keyword,possCmd[j]); + let(&keyword, possCmd[j]); getFullArg_ret: if (ret) { if (keyword[0] == 0) { if (g_rawArgs > arg && strcmp(defaultCmd, "<>")) { /* otherwise, "nothing" was specified */ - printCommandError("", arg, - "?No default answer is available - please be explicit."); + printCommandError("", arg, "?No default answer is available - please be explicit."); ret = 0; goto getFullArg_ret; } } /* Add new field to g_fullArg */ - pntrLet(&g_fullArg,pntrAddElement(g_fullArg)); + pntrLet(&g_fullArg, pntrAddElement(g_fullArg)); if (pntrLen(g_fullArg) != arg + 1) bug(1107); - else let((vstring *)(&g_fullArg[arg]),keyword); + else let((vstring *)(&g_fullArg[arg]), keyword); } /* Deallocate memory */ @@ -1962,183 +1958,161 @@ static flag getFullArg(long arg, const char *cmdList1) { -void parseCommandLine(vstring line) -{ - /* This function breaks up line into individual tokens - and puts them into g_rawArgPntr[]. g_rawArgs is the number of tokens. - g_rawArgPntr[] is the starting position of each token on the line; - the first character on the line has position 1, not 0. - - Spaces, tabs, and newlines are considered white space. Special - one-character - tokens don't have to be surrounded by white space. Characters - inside quotes are considered to be one token, and the quotes are - removed. - - */ - /* Warning: Don't deallocate these vstring constants */ - /*vstring specialOneCharTokens = "()/,=:";*/ - vstring tokenWhiteSpace = " \t\n"; - vstring tokenComment = "!"; - +/* This function breaks up line into individual tokens + and puts them into g_rawArgPntr[]. g_rawArgs is the number of tokens. + g_rawArgPntr[] is the starting position of each token on the line; + the first character on the line has position 1, not 0. - flag mode; - long tokenStart, i, p, lineLen; - - vstring_def(specialOneCharTokens); + Spaces, tabs, and newlines are considered white space. Special + one-character + tokens don't have to be surrounded by white space. Characters + inside quotes are considered to be one token, and the quotes are + removed. +*/ +void parseCommandLine(vstring line) { + /*const char *specialOneCharTokens = "()/,=:";*/ + const char *tokenWhiteSpace = " \t\n"; + const char *tokenComment = "!"; /* Initialization to avoid compiler warning (should not be theoretically necessary) */ - tokenStart = 0; + long tokenStart = 0; - if (!g_toolsMode) { - let(&specialOneCharTokens, "/="); /* List of special one-char tokens */ - } else { - let(&specialOneCharTokens, ""); - } + /* List of special one-char tokens */ + const char* specialOneCharTokens = g_toolsMode ? "" : "/="; - lineLen = len(line); - /* mode: 0 means look for start of token, 1 means look for end of - token, 2 means look for trailing single quote, 3 means look for - trailing double quote */ + long lineLen = len(line); /* only "!" at beginning of line acts as comment. This is done because sometimes ! might be legal as part of a command */ - mode = 0; - for (p = 0; p < lineLen; p++) { + enum mode_t { + MODE_START, // look for start of token + MODE_END, // look for end of token + MODE_SQUOTE, // look for trailing single quote + MODE_DQUOTE, // look for trailing double quote + } mode = MODE_START; + long p = 0; + for (; p < lineLen; p++) { freeTempAlloc(); /* Clean up temp alloc stack to prevent overflow */ - if (mode == 0) { - /* If character is white space, ignore it */ - if (instr(1,tokenWhiteSpace,chr(line[p]))) { - continue; - } - /* If character is comment, we're done */ - if (p == 0 && instr(1,tokenComment,chr(line[p]))) { - break; - } - /* If character is a special token, get it but don't change mode */ - if (instr(1, specialOneCharTokens, chr(line[p]))) { - pntrLet(&g_rawArgPntr, pntrAddElement(g_rawArgPntr)); - nmbrLet(&g_rawArgNmbr, nmbrAddElement(g_rawArgNmbr, p+1)); - /* Save token start */ - let((vstring *)(&g_rawArgPntr[g_rawArgs]), chr(line[p])); - g_rawArgs++; - continue; - } - /* If character is a quote, set start and change mode */ - if (line[p] == '\'') { - mode = 2; - tokenStart = p + 2; - continue; - } - if (line[p] == '\"') { - mode = 3; - tokenStart = p + 2; - continue; - } - /* Character must be start of a token */ - mode = 1; - tokenStart = p + 1; - continue; - } - if (mode == 1) { - /* If character is white space, end token and change mode */ - if (instr(1, tokenWhiteSpace, chr(line[p]))) { - pntrLet(&g_rawArgPntr, pntrAddElement(g_rawArgPntr)); - nmbrLet(&g_rawArgNmbr, nmbrAddElement(g_rawArgNmbr, tokenStart)); - /* Save token start */ - let((vstring *)(&g_rawArgPntr[g_rawArgs]), seg(line, tokenStart, p)); - g_rawArgs++; - mode = 0; - continue; - } + switch (mode) { + case MODE_START: { + /* If character is white space, ignore it */ + if (instr(1, tokenWhiteSpace, chr(line[p]))) continue; + /* If character is comment, we're done */ + if (p == 0 && instr(1, tokenComment, chr(line[p]))) goto parseCommandLine_ret; + + /* If character is a special token, get it but don't change mode */ + if (instr(1, specialOneCharTokens, chr(line[p]))) { + pntrLet(&g_rawArgPntr, pntrAddElement(g_rawArgPntr)); + nmbrLet(&g_rawArgNmbr, nmbrAddElement(g_rawArgNmbr, p+1)); + /* Save token start */ + let((vstring *)(&g_rawArgPntr[g_rawArgs]), chr(line[p])); + g_rawArgs++; + continue; + } + /* If character is a quote, set start and change mode */ + if (line[p] == '\'') { + mode = MODE_SQUOTE; + tokenStart = p + 2; + continue; + } + if (line[p] == '\"') { + mode = MODE_DQUOTE; + tokenStart = p + 2; + continue; + } + /* Character must be start of a token */ + mode = MODE_END; + tokenStart = p + 1; + } break; + + case MODE_END: { + /* If character is white space, end token and change mode */ + if (instr(1, tokenWhiteSpace, chr(line[p]))) { + pntrLet(&g_rawArgPntr, pntrAddElement(g_rawArgPntr)); + nmbrLet(&g_rawArgNmbr, nmbrAddElement(g_rawArgNmbr, tokenStart)); + /* Save token start */ + let((vstring *)(&g_rawArgPntr[g_rawArgs]), seg(line, tokenStart, p)); + g_rawArgs++; + mode = MODE_START; + continue; + } - /* If character is a special token, get it and change mode */ - if (instr(1, specialOneCharTokens, chr(line[p]))) { - pntrLet(&g_rawArgPntr, pntrAddElement(g_rawArgPntr)); - nmbrLet(&g_rawArgNmbr, nmbrAddElement(g_rawArgNmbr, tokenStart)); - /* Save token start */ - let((vstring *)(&g_rawArgPntr[g_rawArgs]),seg(line, tokenStart, p)); - g_rawArgs++; - pntrLet(&g_rawArgPntr, pntrAddElement(g_rawArgPntr)); - nmbrLet(&g_rawArgNmbr, nmbrAddElement(g_rawArgNmbr, p + 1)); - /* Save token start */ - let((vstring *)(&g_rawArgPntr[g_rawArgs]), chr(line[p])); - g_rawArgs++; - mode = 0; - continue; - } + /* If character is a special token, get it and change mode */ + if (instr(1, specialOneCharTokens, chr(line[p]))) { + pntrLet(&g_rawArgPntr, pntrAddElement(g_rawArgPntr)); + nmbrLet(&g_rawArgNmbr, nmbrAddElement(g_rawArgNmbr, tokenStart)); + /* Save token start */ + let((vstring *)(&g_rawArgPntr[g_rawArgs]),seg(line, tokenStart, p)); + g_rawArgs++; + pntrLet(&g_rawArgPntr, pntrAddElement(g_rawArgPntr)); + nmbrLet(&g_rawArgNmbr, nmbrAddElement(g_rawArgNmbr, p + 1)); + /* Save token start */ + let((vstring *)(&g_rawArgPntr[g_rawArgs]), chr(line[p])); + g_rawArgs++; + mode = MODE_START; + continue; + } - /* If character is a quote, set start and change mode */ - if (line[p] == '\'') { - pntrLet(&g_rawArgPntr, pntrAddElement(g_rawArgPntr)); - nmbrLet(&g_rawArgNmbr, nmbrAddElement(g_rawArgNmbr, tokenStart)); - /* Save token start */ - let((vstring *)(&g_rawArgPntr[g_rawArgs]),seg(line, tokenStart,p)); - g_rawArgs++; - mode = 2; - tokenStart = p + 2; - continue; - } - if (line[p] == '\"') { - pntrLet(&g_rawArgPntr, pntrAddElement(g_rawArgPntr)); - nmbrLet(&g_rawArgNmbr, nmbrAddElement(g_rawArgNmbr, tokenStart)); - /* Save token start */ - let((vstring *)(&g_rawArgPntr[g_rawArgs]),seg(line, tokenStart,p)); - g_rawArgs++; - mode = 3; - tokenStart = p + 2; - continue; - } - /* Character must be continuation of the token */ - continue; - } - if (mode == 2 || mode == 3) { - /* If character is a quote, end quote and change mode */ - if (line[p] == '\'' && mode == 2) { - mode = 0; - pntrLet(&g_rawArgPntr, pntrAddElement(g_rawArgPntr)); - nmbrLet(&g_rawArgNmbr, nmbrAddElement(g_rawArgNmbr, tokenStart)); - /* Save token start */ - let((vstring *)(&g_rawArgPntr[g_rawArgs]), seg(line,tokenStart,p)); - g_rawArgs++; - continue; - } - if (line[p] == '\"' && mode == 3) { - mode = 0; - pntrLet(&g_rawArgPntr, pntrAddElement(g_rawArgPntr)); - nmbrLet(&g_rawArgNmbr, nmbrAddElement(g_rawArgNmbr, tokenStart)); - /* Save token start */ - let((vstring *)(&g_rawArgPntr[g_rawArgs]),seg(line, tokenStart,p)); - g_rawArgs++; - continue; - } - /* Character must be continuation of quoted token */ - continue; + /* If character is a quote, set start and change mode */ + if (line[p] == '\'') { + pntrLet(&g_rawArgPntr, pntrAddElement(g_rawArgPntr)); + nmbrLet(&g_rawArgNmbr, nmbrAddElement(g_rawArgNmbr, tokenStart)); + /* Save token start */ + let((vstring *)(&g_rawArgPntr[g_rawArgs]),seg(line, tokenStart, p)); + g_rawArgs++; + mode = MODE_SQUOTE; + tokenStart = p + 2; + continue; + } + if (line[p] == '\"') { + pntrLet(&g_rawArgPntr, pntrAddElement(g_rawArgPntr)); + nmbrLet(&g_rawArgNmbr, nmbrAddElement(g_rawArgNmbr, tokenStart)); + /* Save token start */ + let((vstring *)(&g_rawArgPntr[g_rawArgs]),seg(line, tokenStart, p)); + g_rawArgs++; + mode = MODE_DQUOTE; + tokenStart = p + 2; + continue; + } + /* Character must be continuation of the token */ + } break; + + case MODE_SQUOTE: + case MODE_DQUOTE: { + /* If character is a quote, end quote and change mode */ + if (line[p] == (mode == MODE_SQUOTE ? '\'' : '\"')) { + mode = MODE_START; + pntrLet(&g_rawArgPntr, pntrAddElement(g_rawArgPntr)); + nmbrLet(&g_rawArgNmbr, nmbrAddElement(g_rawArgNmbr, tokenStart)); + /* Save token start */ + let((vstring *)(&g_rawArgPntr[g_rawArgs]),seg(line, tokenStart, p)); + g_rawArgs++; + continue; + } + /* Character must be continuation of quoted token */ + } break; } } /* Finished scanning the line. Finish processing last token. */ - if (mode != 0) { + if (mode != MODE_START) { pntrLet(&g_rawArgPntr, pntrAddElement(g_rawArgPntr)); nmbrLet(&g_rawArgNmbr, nmbrAddElement(g_rawArgNmbr, tokenStart)); /* Save token start */ - let((vstring *)(&g_rawArgPntr[g_rawArgs]),seg(line,tokenStart,p)); + let((vstring *)(&g_rawArgPntr[g_rawArgs]),seg(line, tokenStart, p)); g_rawArgs++; } +parseCommandLine_ret: /* Add length of command line prompt to each argument, to align the error message pointer */ - for (i = 0; i < g_rawArgs; i++) { + for (long i = 0; i < g_rawArgs; i++) { g_rawArgNmbr[i] = g_rawArgNmbr[i] + len(g_commandPrompt); } - - /* Deallocate */ - free_vstring(specialOneCharTokens); } /* parseCommandLine */ -flag lastArgMatches(vstring argString) -{ +flag lastArgMatches(vstring argString) { /* This functions checks to see if the last field was argString */ if (!strcmp(argString, g_fullArg[pntrLen(g_fullArg)-1])) { return (1); @@ -2147,8 +2121,7 @@ flag lastArgMatches(vstring argString) } } /* lastArgMatches */ -flag cmdMatches(vstring cmdString) -{ +flag cmdMatches(vstring cmdString) { /* This function checks that fields 0 through n of g_fullArg match cmdString (separated by spaces). */ long i, j, k; @@ -2178,8 +2151,7 @@ flag cmdMatches(vstring cmdString) } /* cmdMatches */ -long switchPos(vstring swString) -{ +long switchPos(vstring swString) { /* This function checks that fields i through j of g_fullArg match swString (separated by spaces). The first character of swString should be "/" and must be separated from the first field