ReactOS 0.4.16-dev-197-g92996da
if.c
Go to the documentation of this file.
1/*
2 * IF.C - if internal batch command.
3 *
4 *
5 * History:
6 *
7 * 16 Jul 1998 (Hans B Pufal)
8 * started.
9 *
10 * 16 Jul 1998 (John P Price)
11 * Separated commands into individual files.
12 *
13 * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
14 * added config.h include
15 *
16 * 07-Jan-1999 (Eric Kohl)
17 * Added help text ("if /?") and cleaned up.
18 *
19 * 21-Jan-1999 (Eric Kohl)
20 * Unicode and redirection ready!
21 *
22 * 01-Sep-1999 (Eric Kohl)
23 * Fixed help text.
24 *
25 * 17-Feb-2001 (ea)
26 * IF DEFINED variable command
27 *
28 * 28-Apr-2005 (Magnus Olsen) <magnus@greatlord.com>
29 * Remove all hardcoded strings in En.rc
30 *
31 */
32
33#include "precomp.h"
34
35static INT GenericCmp(INT (WINAPI *StringCmp)(LPCTSTR, LPCTSTR),
36 LPCTSTR Left, LPCTSTR Right)
37{
38 TCHAR *end;
39 INT nLeft = _tcstol(Left, &end, 0);
40 if (*end == _T('\0'))
41 {
42 INT nRight = _tcstol(Right, &end, 0);
43 if (*end == _T('\0'))
44 {
45 /* both arguments are numeric */
46 return (nLeft < nRight) ? -1 : (nLeft > nRight);
47 }
48 }
49 return StringCmp(Left, Right);
50}
51
53{
54 TRACE("cmd_if(\'%s\')\n", debugstr_aw(param));
55
56 if (!_tcsncmp (param, _T("/?"), 2))
57 {
59 return 0;
60 }
61
63 return 1;
64}
65
67{
68 INT result = FALSE; /* when set cause 'then' clause to be executed */
70 LPTSTR Left = NULL, Right;
71
72 if (Cmd->If.LeftArg)
73 {
74 Left = DoDelayedExpansion(Cmd->If.LeftArg);
75 if (!Left)
76 return 1;
77 }
78 Right = DoDelayedExpansion(Cmd->If.RightArg);
79 if (!Right)
80 {
81 if (Left) cmd_free(Left);
82 return 1;
83 }
84
85 if (bEnableExtensions && (Cmd->If.Operator == IF_CMDEXTVERSION))
86 {
87 /* IF CMDEXTVERSION n: check if Command Extensions
88 * version is greater or equal to n. */
89 DWORD n = _tcstoul(Right, &param, 10);
90 if (*param != _T('\0'))
91 {
92 error_syntax(Right);
93 goto fail;
94 }
95 result = (CMDEXTVERSION >= n);
96 }
97 else if (bEnableExtensions && (Cmd->If.Operator == IF_DEFINED))
98 {
99 /* IF DEFINED var: check if environment variable exists */
100 result = (GetEnvVarOrSpecial(Right) != NULL);
101 }
102 else if (Cmd->If.Operator == IF_ERRORLEVEL)
103 {
104 /* IF ERRORLEVEL n: check if last exit code is greater or equal to n */
105 INT n = _tcstol(Right, &param, 10);
106 if (*param != _T('\0'))
107 {
108 error_syntax(Right);
109 goto fail;
110 }
111 result = (nErrorLevel >= n);
112 }
113 else if (Cmd->If.Operator == IF_EXIST)
114 {
115 BOOL IsDir;
116 SIZE_T Size;
118 HANDLE hFind;
119 DWORD attrs;
120
121 /* IF EXIST filename: check if file exists (wildcards allowed) */
122 StripQuotes(Right);
123
124 Size = _tcslen(Right);
125 IsDir = (Right[Size - 1] == '\\');
126 if (IsDir)
127 Right[Size - 1] = 0;
128
129 hFind = FindFirstFile(Right, &f);
130 if (hFind != INVALID_HANDLE_VALUE)
131 {
132 attrs = f.dwFileAttributes;
133 FindClose(hFind);
134 }
135 else
136 {
137 /* FindFirstFile fails at the root directory. */
138 attrs = GetFileAttributes(Right);
139 }
140
141 if (attrs == INVALID_FILE_ATTRIBUTES)
142 result = FALSE;
143 else if (IsDir)
145 else
146 result = TRUE;
147
148 if (IsDir)
149 Right[Size - 1] = '\\';
150 }
151 else
152 {
153 /*
154 * Do case-insensitive string comparisons if /I specified.
155 *
156 * Since both strings are user-specific, use kernel32!lstrcmp(i)
157 * instead of CRT!_tcs(i)cmp, so as to use the correct
158 * current thread locale information.
159 */
160 INT (WINAPI *StringCmp)(LPCTSTR, LPCTSTR) =
161 (Cmd->If.Flags & IFFLAG_IGNORECASE) ? lstrcmpi : lstrcmp;
162
163 if (Cmd->If.Operator == IF_STRINGEQ)
164 {
165 /* IF str1 == str2 */
166 result = (StringCmp(Left, Right) == 0);
167 }
168 else if (bEnableExtensions)
169 {
170 result = GenericCmp(StringCmp, Left, Right);
171 switch (Cmd->If.Operator)
172 {
173 case IF_EQU: result = (result == 0); break;
174 case IF_NEQ: result = (result != 0); break;
175 case IF_LSS: result = (result < 0); break;
176 case IF_LEQ: result = (result <= 0); break;
177 case IF_GTR: result = (result > 0); break;
178 case IF_GEQ: result = (result >= 0); break;
179 default: goto unknownOp;
180 }
181 }
182 else
183 {
184unknownOp:
185 ERR("Unknown IF operator 0x%x\n", Cmd->If.Operator);
186 ASSERT(FALSE);
187 goto fail;
188 }
189 }
190
191 if (Left) cmd_free(Left);
192 cmd_free(Right);
193
194 if (result ^ ((Cmd->If.Flags & IFFLAG_NEGATE) != 0))
195 {
196 /* Full condition was true, do the command */
197 return ExecuteCommand(Cmd->Subcommands);
198 }
199 else
200 {
201 /* Full condition was false, do the "else" command if there is one */
202 return ExecuteCommand(Cmd->Subcommands->Next);
203 }
204
205fail:
206 if (Left) cmd_free(Left);
207 cmd_free(Right);
208 return 1;
209}
210
211/* EOF */
INT nErrorLevel
Definition: cmd.c:158
INT ExecuteCommand(IN PARSED_COMMAND *Cmd)
Definition: cmd.c:782
LPCTSTR GetEnvVarOrSpecial(LPCTSTR varName)
Definition: cmd.c:904
PTSTR DoDelayedExpansion(IN PCTSTR Line)
Definition: cmd.c:1640
#define IFFLAG_IGNORECASE
Definition: cmd.h:261
VOID ParseErrorEx(IN PCTSTR s)
Definition: parser.c:227
@ IF_CMDEXTVERSION
Definition: cmd.h:268
@ IF_ERRORLEVEL
Definition: cmd.h:266
@ IF_GTR
Definition: cmd.h:274
@ IF_EQU
Definition: cmd.h:274
@ IF_EXIST
Definition: cmd.h:266
@ IF_GEQ
Definition: cmd.h:274
@ IF_LSS
Definition: cmd.h:274
@ IF_LEQ
Definition: cmd.h:274
@ IF_STRINGEQ
Definition: cmd.h:272
@ IF_DEFINED
Definition: cmd.h:268
@ IF_NEQ
Definition: cmd.h:274
#define IFFLAG_NEGATE
Definition: cmd.h:260
#define CMDEXTVERSION
Definition: cmd.h:32
VOID error_syntax(PCTSTR s)
VOID ConOutResPaging(BOOL StartPaging, UINT resID)
Definition: console.c:178
INT cmd_if(LPTSTR param)
Definition: if.c:52
INT ExecuteIf(PARSED_COMMAND *Cmd)
Definition: if.c:66
static INT GenericCmp(INT(WINAPI *StringCmp)(LPCTSTR, LPCTSTR), LPCTSTR Left, LPCTSTR Right)
Definition: if.c:35
#define debugstr_aw
Definition: precomp.h:44
#define ERR(fmt,...)
Definition: precomp.h:57
#define STRING_IF_HELP1
Definition: resource.h:134
static VOID StripQuotes(LPSTR in)
Definition: cmdcons.c:116
#define cmd_free(ptr)
Definition: cmddbg.h:31
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint end
Definition: gl.h:1545
GLdouble n
Definition: glext.h:7729
GLfloat f
Definition: glext.h:7540
GLfloat param
Definition: glext.h:5796
GLuint64EXT * result
Definition: glext.h:11304
#define _tcstoul
Definition: tchar.h:595
#define _tcsncmp
Definition: tchar.h:1428
#define _tcstol
Definition: tchar.h:594
#define f
Definition: ke_i.h:83
#define ASSERT(a)
Definition: mode.c:44
BOOL bEnableExtensions
Definition: more.c:53
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define INT
Definition: polytest.cpp:20
@ Cmd
Definition: sacdrv.h:278
#define TRACE(s)
Definition: solgame.cpp:4
ULONG_PTR SIZE_T
Definition: typedefs.h:80
int32_t INT
Definition: typedefs.h:58
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
#define _T(x)
Definition: vfdio.h:22
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_DEVICE_PROPERTY_DATA _In_ DEVPROPTYPE _In_ ULONG Size
Definition: wdfdevice.h:4533
#define GetFileAttributes
Definition: winbase.h:3839
#define lstrcmp
Definition: winbase.h:3896
#define lstrcmpi
Definition: winbase.h:3897
#define FindFirstFile
Definition: winbase.h:3806
#define WINAPI
Definition: msvc.h:6
char TCHAR
Definition: xmlstorage.h:189
const CHAR * LPCTSTR
Definition: xmlstorage.h:193
CHAR * LPTSTR
Definition: xmlstorage.h:192
#define _tcslen
Definition: xmlstorage.h:198