cmd: Implement semantic for chaining in ||, | and && operators.

Signed-off-by: Eric Pouech <epouech@codeweavers.com>
This commit is contained in:
Eric Pouech 2024-06-27 16:21:35 +02:00 committed by Alexandre Julliard
parent 9c717825dc
commit bf9a465e95
3 changed files with 94 additions and 58 deletions

View file

@ -262,7 +262,7 @@ a2
b1
b2
c1
@todo_wine@---
---
d1
d2
d3
@ -271,7 +271,7 @@ e2
e3
f1
f2
@todo_wine@---
---
g1
g2
g3
@ -280,19 +280,19 @@ h2
h3
i1
i2
@todo_wine@---
---
j1
@todo_wine@j3
@todo_wine@---
j3
---
k1
@todo_wine@---
---
l1
@todo_wine@---
---
--- chain failure
a1
a2
b1
@todo_wine@---
---
c1
c2
d1
@ -300,24 +300,24 @@ d2
d3
e1
e2
@todo_wine@---
---
f1
f2
f3
g1
@todo_wine@g3
@todo_wine@---
g3
---
h1
@todo_wine@---
---
i1
@todo_wine@i3
@todo_wine@---
i3
---
j1
j2
j3
k1
k2
@todo_wine@---
---
l1
l2
l3
@ -330,7 +330,7 @@ b2
b3
c1
c2
@todo_wine@---
---
d1
d2
d3
@ -339,34 +339,34 @@ e2
e3
f1
f2
@todo_wine@---
---
g1
@todo_wine@---
---
h1
@todo_wine@---
---
i1
@todo_wine@---
---
j1
j2
j3
k1
k2
@todo_wine@---
---
l1
l2
l3
m1
@todo_wine@---
---
n1
@todo_wine@---
---
o1
@todo_wine@---
---
p1
p2
p3
q1
q2
@todo_wine@---
---
r1
r2
r3
@ -378,13 +378,13 @@ b2
c1
c3
d1
@todo_wine@---
---
e1
e3
f2
f3
g2
@todo_wine@---
---
h2
h3
i3
@ -398,44 +398,44 @@ f4:[f3:[f2:[f1,f2],f3],f4]@or_broken@f4:[f3:[f2:,f3],f4]@or_broken@f4:[f3:,f4]
--- chain else
a1
b2
@todo_wine@---
---
c3
@todo_wine@---
---
d3
@todo_wine@---
@todo_wine@---
@todo_wine@---
@todo_wine@---
@todo_wine@---
---
---
---
---
---
--- chain else (if true)
a1 else echo a2
b2 else echo b3
c1
c2 else echo c3
d1
@todo_wine@---
---
e1
e2 else echo e3
f3
g1 else echo g2
g3
h1 else echo h2
@todo_wine@---
---
i1 else echo i2
i3
@todo_wine@j2@space@
@todo_wine@---
---
k1
k2
l1
@todo_wine@---
---
m1
m2
n1
o1
p1
q1
@todo_wine@---
---
--- chain else (if false)
j3
---
@ -446,25 +446,25 @@ n3
o2
o3
p2
@todo_wine@---
---
q2
q3
------------- Testing internal commands return codes
--- call and IF/FOR blocks
SUCCESS 0
@todo_wine@FAILURE 33
@todo_wine@foo@space@
@todo_wine@SUCCESS 666
@todo_wine@FAILURE 1
FAILURE 33
foo@space@
SUCCESS 666
@todo_wine@SUCCESS 666
@todo_wine@FAILURE 33
@todo_wine@FAILURE 34
FAILURE 1
SUCCESS 666
@todo_wine@SUCCESS 666
@todo_wine@SUCCESS 0
@todo_wine@FAILURE 33
@todo_wine@---
SUCCESS 666
FAILURE 33
FAILURE 34
SUCCESS 666
SUCCESS 666
SUCCESS 0
FAILURE 33
---
------------ Testing 'set' ------------
1
0
@ -654,13 +654,13 @@ bar2@space@
foo2
foobar deleted
--- on success conditional and
@todo_wine@foo3 not created
foo3 not created
bar4@space@
foo4
--- on failure conditional or
foo5
foo6@space@
@todo_wine@------------ Testing cd ------------
------------ Testing cd ------------
singleFile
Current dir: @drive@@path@foobar@or_broken@Current dir:@space@
@drive@@path@foobar

View file

@ -156,6 +156,8 @@ typedef int RETURN_CODE;
#define RETURN_CODE_SYNTAX_ERROR 255
#define RETURN_CODE_CANT_LAUNCH 9009
#define RETURN_CODE_ABORTED (-999999)
/* temporary to detect builtin commands not migrated to handle return code */
#define RETURN_CODE_OLD_CHAINING (-999998)
void WCMD_assoc (const WCHAR *, BOOL);
void WCMD_batch(WCHAR *, WCHAR *, WCHAR *, HANDLE);

View file

@ -1734,7 +1734,7 @@ static BOOL set_std_redirections(CMD_REDIRECTION *redir)
*/
static RETURN_CODE execute_single_command(const WCHAR *command)
{
RETURN_CODE return_code = NO_ERROR;
RETURN_CODE return_code;
WCHAR *cmd, *parms_start;
int status, cmd_index, count;
WCHAR *whichcmd;
@ -1791,6 +1791,7 @@ static RETURN_CODE execute_single_command(const WCHAR *command)
WINE_TRACE("Got directory %s as %s\n", wine_dbgstr_w(envvar), wine_dbgstr_w(cmd));
status = SetCurrentDirectoryW(cmd);
if (!status) WCMD_print_error ();
return_code = ERROR_INVALID_FUNCTION;
goto cleanup;
}
@ -1805,6 +1806,7 @@ static RETURN_CODE execute_single_command(const WCHAR *command)
}
return_code = RETURN_CODE_OLD_CHAINING;
switch (cmd_index) {
case WCMD_CALL:
@ -1936,6 +1938,7 @@ static RETURN_CODE execute_single_command(const WCHAR *command)
default:
prev_echo_mode = echo_mode;
WCMD_run_program (whichcmd, FALSE);
return_code = errorlevel;
echo_mode = prev_echo_mode;
}
@ -3659,6 +3662,16 @@ static RETURN_CODE for_control_execute(CMD_FOR_CONTROL *for_ctrl, CMD_NODE *node
return return_code;
}
static RETURN_CODE temp_fixup_return_code(CMD_NODE *node, RETURN_CODE return_code, RETURN_CODE fallback_return_code)
{
if (return_code == RETURN_CODE_OLD_CHAINING)
{
FIXME("Not migrated (%ls) used in chaining\n", node->op == CMD_SINGLE ? node->command->command : L"Too complex");
return_code = fallback_return_code;
}
return return_code;
}
RETURN_CODE node_execute(CMD_NODE *node)
{
HANDLE old_stdhandles[3] = {GetStdHandle (STD_INPUT_HANDLE),
@ -3674,7 +3687,7 @@ RETURN_CODE node_execute(CMD_NODE *node)
{
WCMD_print_error();
/* FIXME potentially leaking here (if first redir created ok, and second failed */
return ERROR_INVALID_FUNCTION;
return errorlevel = ERROR_INVALID_FUNCTION;
}
switch (node->op)
{
@ -3684,12 +3697,28 @@ RETURN_CODE node_execute(CMD_NODE *node)
else return_code = NO_ERROR;
break;
case CMD_CONCAT:
case CMD_ONSUCCESS:
case CMD_ONFAILURE:
return_code = node_execute(node->left);
if (return_code != RETURN_CODE_ABORTED)
return_code = node_execute(node->right);
break;
case CMD_ONSUCCESS:
return_code = node_execute(node->left);
return_code = temp_fixup_return_code(node->left, return_code, NO_ERROR);
if (return_code == NO_ERROR)
{
return_code = node_execute(node->right);
temp_fixup_return_code(node->right, return_code, 0 /* not used */);
}
break;
case CMD_ONFAILURE:
return_code = node_execute(node->left);
return_code = temp_fixup_return_code(node->left, return_code, ERROR_INVALID_FUNCTION);
if (return_code != NO_ERROR)
{
return_code = node_execute(node->right);
temp_fixup_return_code(node->right, return_code, 0 /* not used */);
}
break;
case CMD_PIPE:
{
static SECURITY_ATTRIBUTES sa = {.nLength = sizeof(sa), .lpSecurityDescriptor = NULL, .bInheritHandle = TRUE};
@ -3714,11 +3743,13 @@ RETURN_CODE node_execute(CMD_NODE *node)
output = redirection_create_file(REDIR_WRITE_TO, 1, filename);
if (set_std_redirections(output))
{
return_code = node_execute(node->left);
RETURN_CODE return_code_left = node_execute(node->left);
return_code = NO_ERROR;
CloseHandle(GetStdHandle(STD_OUTPUT_HANDLE));
SetStdHandle(STD_OUTPUT_HANDLE, old_stdhandles[1]);
return_code = temp_fixup_return_code(node->left, return_code, NO_ERROR);
if (return_code == NO_ERROR)
{
HANDLE h = CreateFileW(filename, GENERIC_READ,
@ -3728,10 +3759,13 @@ RETURN_CODE node_execute(CMD_NODE *node)
{
SetStdHandle(STD_INPUT_HANDLE, h);
return_code = node_execute(node->right);
temp_fixup_return_code(node->right, return_code, 0 /* not used */);
}
else return_code = ERROR_INVALID_FUNCTION;
}
DeleteFileW(filename);
if (return_code_left != NO_ERROR || return_code != NO_ERROR)
errorlevel = ERROR_INVALID_FUNCTION;
}
else return_code = ERROR_INVALID_FUNCTION;
redirection_dispose_list(output);