mirror of
https://github.com/reactos/reactos.git
synced 2026-06-08 00:46:10 +08:00
[CMD] CALL: Fix the implementation of the CALL command, make it more compatible with Windows' CMD.
- Fail if no parameter is provided.
- The "CALL :label args..." syntax is available only when command extensions
are enabled. Fail if this syntax is used outside of a batch context.
- Reparse the CALL command parameter with the command parser, in order
to accurately parse and interpret it as a possible command (including
escape carets, etc...) and not duplicate the logic.
** CURRENT Windows' CMD-compatibility LIMITATION ** (may be lifted in
a "ROS-specific" running mode of CMD): only allow standard commands to
be specified as parameter of the CALL command.
This reparsing behaviour can be observed in Windows' CMD, by dumping
the interpreted commands after enabling the cmd!fDumpParse flag from
a debugger (using public symbols).
- When reparsing, we should tell the parser to NOT ignore lines that
start with a colon, because in this situation these are to be
considered as valid "commands" (for parsing "CALL :label").
* For Windows' CMD-compatibility, the remaining escape carets need to
be doubled again so that, after the new parser step, they are escaped
back to their original form. But then we also need to do it the "buggy"
way à la Windows, where carets in quotes are doubled either! However
when being re-parsed, since they are in quotes they remain doubled!!
(see "Phase 6" in https://stackoverflow.com/a/4095133/13530036 ).
* A MSCMD_CALL_QUIRKS define allows to disable this buggy behaviour,
and instead tell the parser to not not interpret the escape carets.
- When initializing a new batch context when the "CALL :label" syntax is
used, ensure that we reuse the same batch file position pointer as its
parent, so as to have correct call label ordering behaviour.
That is,
:label
ECHO hi
CALL :label
:label
ECHO bye
should display:
hi
bye
bye
i.e., the CALL calls the second label instead of the first one (and
thus entering into an infinite loop).
Finally, the "CALL :label" syntax strips the first ':' away, so, as a
side-effect, the command "CALL :EOF" fails (otherwise it would perform
a "GOTO :EOF" and succeeds), while "CALL ::EOF" succeeds.
Fixes some cmd_winetests.
This commit is contained in:
@@ -399,9 +399,28 @@ INT Batch(LPTSTR fullname, LPTSTR firstword, LPTSTR param, PARSED_COMMAND *Cmd)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Check if this is a "CALL :label" */
|
||||
if (*firstword == _T(':'))
|
||||
ret = cmd_goto(firstword);
|
||||
/* If this is a "CALL :label args ...", call a subroutine of
|
||||
* the current batch file, only if extensions are enabled. */
|
||||
if (bEnableExtensions && (*firstword == _T(':')))
|
||||
{
|
||||
LPTSTR expLabel;
|
||||
|
||||
/* Position at the place of the parent file (which is the same as the caller) */
|
||||
bc->mempos = (bc->prev ? bc->prev->mempos : 0);
|
||||
|
||||
/*
|
||||
* Jump to the label. Strip the label's colon; as a side-effect
|
||||
* this will forbid "CALL :EOF"; however "CALL ::EOF" will work!
|
||||
*/
|
||||
bc->current = Cmd;
|
||||
++firstword;
|
||||
|
||||
/* Expand the label only! (simulate a GOTO command as in Windows' CMD) */
|
||||
expLabel = DoDelayedExpansion(firstword);
|
||||
ret = cmd_goto(expLabel ? expLabel : firstword);
|
||||
if (expLabel)
|
||||
cmd_free(expLabel);
|
||||
}
|
||||
|
||||
/* If we have created a new context, don't return
|
||||
* until this batch file has completed. */
|
||||
@@ -548,8 +567,16 @@ LPTSTR ReadBatchLine(VOID)
|
||||
|
||||
TRACE("ReadBatchLine(): textline: \'%s\'\n", debugstr_aw(textline));
|
||||
|
||||
#if 1
|
||||
//
|
||||
// FIXME: This is redundant, but keep it for the moment until we correctly
|
||||
// hande the end-of-file situation here, in ReadLine() and in the parser.
|
||||
// (In an EOF, the previous BatchGetString() call will return FALSE but
|
||||
// we want not to run the ExitBatch() at first, but wait later to do it.)
|
||||
//
|
||||
if (textline[_tcslen(textline) - 1] != _T('\n'))
|
||||
_tcscat(textline, _T("\n"));
|
||||
#endif
|
||||
|
||||
return textline;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user