]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellLevel1CommandsLib/If.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / ShellPkg / Library / UefiShellLevel1CommandsLib / If.c
CommitLineData
a405b86d 1/** @file\r
2 Main file for If and else shell level 1 function.\r
3\r
c011b6c9 4 (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>\r
ba0014b9 5 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
56ba3746 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
a405b86d 7\r
8**/\r
9\r
10#include "UefiShellLevel1CommandsLib.h"\r
11#include <Library/PrintLib.h>\r
12\r
a405b86d 13typedef enum {\r
77dcec12 14 EndTagOr,\r
15 EndTagAnd,\r
16 EndTagThen,\r
17 EndTagMax\r
a405b86d 18} END_TAG_TYPE;\r
19\r
20typedef enum {\r
77dcec12 21 OperatorGreaterThan,\r
22 OperatorLessThan,\r
23 OperatorEqual,\r
24 OperatorNotEqual,\r
25 OperatorGreatorOrEqual,\r
26 OperatorLessOrEqual,\r
27 OperatorUnisgnedGreaterThan,\r
28 OperatorUnsignedLessThan,\r
29 OperatorUnsignedGreaterOrEqual,\r
30 OperatorUnsignedLessOrEqual,\r
31 OperatorMax\r
a405b86d 32} BIN_OPERATOR_TYPE;\r
33\r
77dcec12 34/**\r
35 Extract the next fragment, if there is one.\r
36\r
4ff7e37b
ED
37 @param[in, out] Statement The current remaining statement.\r
38 @param[in] Fragment The current fragment.\r
581c0389
RN
39 @param[out] Match TRUE when there is another Fragment in Statement,\r
40 FALSE otherwise.\r
77dcec12 41\r
581c0389
RN
42 @retval EFI_SUCCESS The match operation is performed successfully.\r
43 @retval EFI_OUT_OF_RESOURCES Out of resources.\r
77dcec12 44**/\r
581c0389 45EFI_STATUS\r
a405b86d 46IsNextFragment (\r
47d20b54
MK
47 IN OUT CONST CHAR16 **Statement,\r
48 IN CONST CHAR16 *Fragment,\r
49 OUT BOOLEAN *Match\r
a405b86d 50 )\r
51{\r
47d20b54 52 CHAR16 *Tester;\r
a405b86d 53\r
54 Tester = NULL;\r
55\r
47d20b54 56 Tester = StrnCatGrow (&Tester, NULL, *Statement, StrLen (Fragment));\r
581c0389
RN
57 if (Tester == NULL) {\r
58 return EFI_OUT_OF_RESOURCES;\r
59 }\r
47d20b54
MK
60\r
61 Tester[StrLen (Fragment)] = CHAR_NULL;\r
62 if (gUnicodeCollation->StriColl (\r
63 gUnicodeCollation,\r
64 (CHAR16 *)Fragment,\r
65 Tester\r
66 ) == 0)\r
67 {\r
a405b86d 68 //\r
69 // increment the string pointer to the end of what we found and then chop off spaces...\r
70 //\r
47d20b54 71 *Statement += StrLen (Fragment);\r
a405b86d 72 while (*Statement[0] == L' ') {\r
1ca79586 73 (*Statement)++;\r
a405b86d 74 }\r
47d20b54 75\r
581c0389
RN
76 *Match = TRUE;\r
77 } else {\r
78 *Match = FALSE;\r
a405b86d 79 }\r
47d20b54
MK
80\r
81 FreePool (Tester);\r
581c0389 82 return EFI_SUCCESS;\r
a405b86d 83}\r
84\r
77dcec12 85/**\r
86 Determine if String represents a valid profile.\r
87\r
88 @param[in] String The pointer to the string to test.\r
89\r
90 @retval TRUE String is a valid profile.\r
91 @retval FALSE String is not a valid profile.\r
92**/\r
a405b86d 93BOOLEAN\r
a405b86d 94IsValidProfile (\r
47d20b54 95 IN CONST CHAR16 *String\r
a405b86d 96 )\r
97{\r
98 CONST CHAR16 *ProfilesString;\r
99 CONST CHAR16 *TempLocation;\r
100\r
47d20b54
MK
101 ProfilesString = ShellGetEnvironmentVariable (L"profiles");\r
102 ASSERT (ProfilesString != NULL);\r
103 TempLocation = StrStr (ProfilesString, String);\r
104 if ((TempLocation != NULL) && (*(TempLocation-1) == L';') && (*(TempLocation+StrLen (String)) == L';')) {\r
a405b86d 105 return (TRUE);\r
106 }\r
47d20b54 107\r
a405b86d 108 return (FALSE);\r
109}\r
110\r
77dcec12 111/**\r
112 Do a comparison between 2 things.\r
113\r
114 @param[in] Compare1 The first item to compare.\r
115 @param[in] Compare2 The second item to compare.\r
116 @param[in] BinOp The type of comparison to perform.\r
117 @param[in] CaseInsensitive TRUE to do non-case comparison, FALSE otherwise.\r
118 @param[in] ForceStringCompare TRUE to force string comparison, FALSE otherwise.\r
119\r
120 @return The result of the comparison.\r
121**/\r
a405b86d 122BOOLEAN\r
a405b86d 123TestOperation (\r
124 IN CONST CHAR16 *Compare1,\r
125 IN CONST CHAR16 *Compare2,\r
126 IN CONST BIN_OPERATOR_TYPE BinOp,\r
127 IN CONST BOOLEAN CaseInsensitive,\r
128 IN CONST BOOLEAN ForceStringCompare\r
129 )\r
130{\r
47d20b54
MK
131 INTN Cmp1;\r
132 INTN Cmp2;\r
a405b86d 133\r
134 //\r
135 // "Compare1 BinOp Compare2"\r
136 //\r
137 switch (BinOp) {\r
47d20b54
MK
138 case OperatorUnisgnedGreaterThan:\r
139 case OperatorGreaterThan:\r
140 if (ForceStringCompare || !ShellIsHexOrDecimalNumber (Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber (Compare2, FALSE, FALSE)) {\r
141 //\r
142 // string compare\r
143 //\r
144 if ((CaseInsensitive && (StringNoCaseCompare (&Compare1, &Compare2) > 0)) || (StringCompare (&Compare1, &Compare2) > 0)) {\r
a405b86d 145 return (TRUE);\r
146 }\r
147 } else {\r
47d20b54
MK
148 //\r
149 // numeric compare\r
150 //\r
151 if (Compare1[0] == L'-') {\r
152 Cmp1 = 0 - (INTN)ShellStrToUintn (Compare1+1);\r
153 } else {\r
154 Cmp1 = (INTN)ShellStrToUintn (Compare1);\r
155 }\r
156\r
157 if (Compare2[0] == L'-') {\r
158 Cmp2 = 0 - (INTN)ShellStrToUintn (Compare2+1);\r
159 } else {\r
160 Cmp2 = (INTN)ShellStrToUintn (Compare2);\r
161 }\r
162\r
163 if (BinOp == OperatorGreaterThan) {\r
164 if (Cmp1 > Cmp2) {\r
165 return (TRUE);\r
166 }\r
167 } else {\r
168 if ((UINTN)Cmp1 > (UINTN)Cmp2) {\r
169 return (TRUE);\r
170 }\r
a405b86d 171 }\r
172 }\r
47d20b54
MK
173\r
174 return (FALSE);\r
175 case OperatorUnsignedLessThan:\r
176 case OperatorLessThan:\r
177 if (ForceStringCompare || !ShellIsHexOrDecimalNumber (Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber (Compare2, FALSE, FALSE)) {\r
178 //\r
179 // string compare\r
180 //\r
181 if ((CaseInsensitive && (StringNoCaseCompare (&Compare1, &Compare2) < 0)) || (StringCompare (&Compare1, &Compare2) < 0)) {\r
182 return (TRUE);\r
183 }\r
a405b86d 184 } else {\r
47d20b54
MK
185 //\r
186 // numeric compare\r
187 //\r
188 if (Compare1[0] == L'-') {\r
189 Cmp1 = 0 - (INTN)ShellStrToUintn (Compare1+1);\r
190 } else {\r
191 Cmp1 = (INTN)ShellStrToUintn (Compare1);\r
192 }\r
193\r
194 if (Compare2[0] == L'-') {\r
195 Cmp2 = 0 - (INTN)ShellStrToUintn (Compare2+1);\r
196 } else {\r
197 Cmp2 = (INTN)ShellStrToUintn (Compare2);\r
198 }\r
199\r
200 if (BinOp == OperatorLessThan) {\r
201 if (Cmp1 < Cmp2) {\r
202 return (TRUE);\r
203 }\r
204 } else {\r
205 if ((UINTN)Cmp1 < (UINTN)Cmp2) {\r
206 return (TRUE);\r
207 }\r
208 }\r
a405b86d 209 }\r
47d20b54
MK
210\r
211 return (FALSE);\r
212 case OperatorEqual:\r
213 if (ForceStringCompare || !ShellIsHexOrDecimalNumber (Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber (Compare2, FALSE, FALSE)) {\r
214 //\r
215 // string compare\r
216 //\r
217 if ((CaseInsensitive && (StringNoCaseCompare (&Compare1, &Compare2) == 0)) || (StringCompare (&Compare1, &Compare2) == 0)) {\r
a405b86d 218 return (TRUE);\r
219 }\r
220 } else {\r
47d20b54
MK
221 //\r
222 // numeric compare\r
223 //\r
224 if (Compare1[0] == L'-') {\r
225 Cmp1 = 0 - (INTN)ShellStrToUintn (Compare1+1);\r
226 } else {\r
227 Cmp1 = (INTN)ShellStrToUintn (Compare1);\r
228 }\r
229\r
230 if (Compare2[0] == L'-') {\r
231 Cmp2 = 0 - (INTN)ShellStrToUintn (Compare2+1);\r
232 } else {\r
233 Cmp2 = (INTN)ShellStrToUintn (Compare2);\r
234 }\r
235\r
236 if (Cmp1 == Cmp2) {\r
a405b86d 237 return (TRUE);\r
238 }\r
239 }\r
240\r
47d20b54
MK
241 return (FALSE);\r
242 case OperatorNotEqual:\r
243 if (ForceStringCompare || !ShellIsHexOrDecimalNumber (Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber (Compare2, FALSE, FALSE)) {\r
244 //\r
245 // string compare\r
246 //\r
247 if ((CaseInsensitive && (StringNoCaseCompare (&Compare1, &Compare2) != 0)) || (StringCompare (&Compare1, &Compare2) != 0)) {\r
a405b86d 248 return (TRUE);\r
249 }\r
250 } else {\r
47d20b54
MK
251 //\r
252 // numeric compare\r
253 //\r
254 if (Compare1[0] == L'-') {\r
255 Cmp1 = 0 - (INTN)ShellStrToUintn (Compare1+1);\r
256 } else {\r
257 Cmp1 = (INTN)ShellStrToUintn (Compare1);\r
258 }\r
259\r
260 if (Compare2[0] == L'-') {\r
261 Cmp2 = 0 - (INTN)ShellStrToUintn (Compare2+1);\r
262 } else {\r
263 Cmp2 = (INTN)ShellStrToUintn (Compare2);\r
264 }\r
265\r
266 if (Cmp1 != Cmp2) {\r
a405b86d 267 return (TRUE);\r
268 }\r
269 }\r
47d20b54
MK
270\r
271 return (FALSE);\r
272 case OperatorUnsignedGreaterOrEqual:\r
273 case OperatorGreatorOrEqual:\r
274 if (ForceStringCompare || !ShellIsHexOrDecimalNumber (Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber (Compare2, FALSE, FALSE)) {\r
275 //\r
276 // string compare\r
277 //\r
278 if ((CaseInsensitive && (StringNoCaseCompare (&Compare1, &Compare2) >= 0)) || (StringCompare (&Compare1, &Compare2) >= 0)) {\r
279 return (TRUE);\r
280 }\r
a405b86d 281 } else {\r
47d20b54
MK
282 //\r
283 // numeric compare\r
284 //\r
285 if (Compare1[0] == L'-') {\r
286 Cmp1 = 0 - (INTN)ShellStrToUintn (Compare1+1);\r
287 } else {\r
288 Cmp1 = (INTN)ShellStrToUintn (Compare1);\r
289 }\r
290\r
291 if (Compare2[0] == L'-') {\r
292 Cmp2 = 0 - (INTN)ShellStrToUintn (Compare2+1);\r
293 } else {\r
294 Cmp2 = (INTN)ShellStrToUintn (Compare2);\r
295 }\r
296\r
297 if (BinOp == OperatorGreatorOrEqual) {\r
298 if (Cmp1 >= Cmp2) {\r
299 return (TRUE);\r
300 }\r
301 } else {\r
302 if ((UINTN)Cmp1 >= (UINTN)Cmp2) {\r
303 return (TRUE);\r
304 }\r
305 }\r
a405b86d 306 }\r
47d20b54
MK
307\r
308 return (FALSE);\r
309 case OperatorLessOrEqual:\r
310 case OperatorUnsignedLessOrEqual:\r
311 if (ForceStringCompare || !ShellIsHexOrDecimalNumber (Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber (Compare2, FALSE, FALSE)) {\r
312 //\r
313 // string compare\r
314 //\r
315 if ((CaseInsensitive && (StringNoCaseCompare (&Compare1, &Compare2) <= 0)) || (StringCompare (&Compare1, &Compare2) <= 0)) {\r
a405b86d 316 return (TRUE);\r
317 }\r
318 } else {\r
47d20b54
MK
319 //\r
320 // numeric compare\r
321 //\r
322 if (Compare1[0] == L'-') {\r
323 Cmp1 = 0 - (INTN)ShellStrToUintn (Compare1+1);\r
324 } else {\r
325 Cmp1 = (INTN)ShellStrToUintn (Compare1);\r
326 }\r
327\r
328 if (Compare2[0] == L'-') {\r
329 Cmp2 = 0 - (INTN)ShellStrToUintn (Compare2+1);\r
330 } else {\r
331 Cmp2 = (INTN)ShellStrToUintn (Compare2);\r
332 }\r
333\r
334 if (BinOp == OperatorLessOrEqual) {\r
335 if (Cmp1 <= Cmp2) {\r
336 return (TRUE);\r
337 }\r
338 } else {\r
339 if ((UINTN)Cmp1 <= (UINTN)Cmp2) {\r
340 return (TRUE);\r
341 }\r
a405b86d 342 }\r
343 }\r
47d20b54
MK
344\r
345 return (FALSE);\r
346 default:\r
347 ASSERT (FALSE);\r
348 return (FALSE);\r
a405b86d 349 }\r
a405b86d 350}\r
351\r
77dcec12 352/**\r
353 Process an if statement and determine if its is valid or not.\r
354\r
ba0014b9 355 @param[in, out] PassingState Opon entry, the current state. Upon exit,\r
4ff7e37b
ED
356 the new state.\r
357 @param[in] StartParameterNumber The number of the first parameter of\r
358 this statement.\r
359 @param[in] EndParameterNumber The number of the final parameter of\r
360 this statement.\r
361 @param[in] OperatorToUse The type of termination operator.\r
362 @param[in] CaseInsensitive TRUE for case insensitive, FALSE otherwise.\r
363 @param[in] ForceStringCompare TRUE for all string based, FALSE otherwise.\r
77dcec12 364\r
365 @retval EFI_INVALID_PARAMETER A parameter was invalid.\r
ba0014b9 366 @retval EFI_SUCCESS The operation was successful.\r
77dcec12 367**/\r
a405b86d 368EFI_STATUS\r
a405b86d 369ProcessStatement (\r
47d20b54
MK
370 IN OUT BOOLEAN *PassingState,\r
371 IN UINTN StartParameterNumber,\r
372 IN UINTN EndParameterNumber,\r
373 IN CONST END_TAG_TYPE OperatorToUse,\r
374 IN CONST BOOLEAN CaseInsensitive,\r
375 IN CONST BOOLEAN ForceStringCompare\r
a405b86d 376 )\r
377{\r
47d20b54
MK
378 EFI_STATUS Status;\r
379 BOOLEAN OperationResult;\r
380 BOOLEAN NotPresent;\r
381 CHAR16 *StatementWalker;\r
382 BIN_OPERATOR_TYPE BinOp;\r
383 CHAR16 *Compare1;\r
384 CHAR16 *Compare2;\r
385 CHAR16 HexString[20];\r
386 CHAR16 *TempSpot;\r
387 BOOLEAN Match;\r
388\r
389 ASSERT ((END_TAG_TYPE)OperatorToUse != EndTagThen);\r
a405b86d 390\r
391 Status = EFI_SUCCESS;\r
77dcec12 392 BinOp = OperatorMax;\r
a405b86d 393 OperationResult = FALSE;\r
1b031953 394 Match = FALSE;\r
a405b86d 395 StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber];\r
47d20b54 396 if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"not", &Match)) && Match) {\r
a405b86d 397 NotPresent = TRUE;\r
398 StatementWalker = gEfiShellParametersProtocol->Argv[++StartParameterNumber];\r
399 } else {\r
400 NotPresent = FALSE;\r
401 }\r
402\r
403 //\r
404 // now check for 'boolfunc' operators\r
405 //\r
47d20b54
MK
406 if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"isint", &Match)) && Match) {\r
407 if ( !EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"(", &Match)) && Match\r
408 && (StatementWalker[StrLen (StatementWalker)-1] == L')'))\r
409 {\r
410 StatementWalker[StrLen (StatementWalker)-1] = CHAR_NULL;\r
411 OperationResult = ShellIsHexOrDecimalNumber (StatementWalker, FALSE, FALSE);\r
a405b86d 412 } else {\r
413 Status = EFI_INVALID_PARAMETER;\r
47d20b54 414 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"isint");\r
a405b86d 415 }\r
47d20b54
MK
416 } else if ((!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"exists", &Match)) && Match) ||\r
417 (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"exist", &Match)) && Match))\r
418 {\r
419 if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"(", &Match)) && Match &&\r
420 (StatementWalker[StrLen (StatementWalker)-1] == L')'))\r
421 {\r
422 StatementWalker[StrLen (StatementWalker)-1] = CHAR_NULL;\r
a405b86d 423 //\r
424 // is what remains a file in CWD???\r
425 //\r
47d20b54
MK
426 OperationResult = (BOOLEAN)(ShellFileExists (StatementWalker) == EFI_SUCCESS);\r
427 } else if ((StatementWalker[0] == CHAR_NULL) && (StartParameterNumber+1 == EndParameterNumber)) {\r
428 OperationResult = (BOOLEAN)(ShellFileExists (gEfiShellParametersProtocol->Argv[++StartParameterNumber]) == EFI_SUCCESS);\r
a405b86d 429 } else {\r
47d20b54 430 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"exist(s)");\r
a405b86d 431 Status = EFI_INVALID_PARAMETER;\r
432 }\r
47d20b54
MK
433 } else if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"available", &Match)) && Match) {\r
434 if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"(", &Match)) && Match &&\r
435 (StatementWalker[StrLen (StatementWalker)-1] == L')'))\r
436 {\r
437 StatementWalker[StrLen (StatementWalker)-1] = CHAR_NULL;\r
a405b86d 438 //\r
439 // is what remains a file in the CWD or path???\r
440 //\r
47d20b54 441 OperationResult = (BOOLEAN)(ShellIsFileInPath (StatementWalker) == EFI_SUCCESS);\r
a405b86d 442 } else {\r
47d20b54 443 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"available");\r
a405b86d 444 Status = EFI_INVALID_PARAMETER;\r
445 }\r
47d20b54
MK
446 } else if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"profile", &Match)) && Match) {\r
447 if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"(", &Match)) && Match &&\r
448 (StatementWalker[StrLen (StatementWalker)-1] == L')'))\r
449 {\r
a405b86d 450 //\r
451 // Chop off that ')'\r
452 //\r
47d20b54
MK
453 StatementWalker[StrLen (StatementWalker)-1] = CHAR_NULL;\r
454 OperationResult = IsValidProfile (StatementWalker);\r
a405b86d 455 } else {\r
47d20b54 456 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"profile");\r
a405b86d 457 Status = EFI_INVALID_PARAMETER;\r
458 }\r
459 } else if (StartParameterNumber+1 >= EndParameterNumber) {\r
47d20b54
MK
460 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[StartParameterNumber]);\r
461 Status = EFI_INVALID_PARAMETER;\r
a405b86d 462 } else {\r
463 //\r
464 // must be 'item binop item' style\r
465 //\r
466 Compare1 = NULL;\r
467 Compare2 = NULL;\r
77dcec12 468 BinOp = OperatorMax;\r
a405b86d 469\r
470 //\r
471 // get the first item\r
472 //\r
473 StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber];\r
47d20b54
MK
474 if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"efierror", &Match)) && Match) {\r
475 TempSpot = StrStr (StatementWalker, L")");\r
476 if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"(", &Match)) && Match && (TempSpot != NULL)) {\r
a405b86d 477 *TempSpot = CHAR_NULL;\r
47d20b54
MK
478 if (ShellIsHexOrDecimalNumber (StatementWalker, FALSE, FALSE)) {\r
479 UnicodeSPrint (HexString, sizeof (HexString), L"0x%x", ShellStrToUintn (StatementWalker)|MAX_BIT);\r
480 ASSERT (Compare1 == NULL);\r
481 Compare1 = StrnCatGrow (&Compare1, NULL, HexString, 0);\r
482 StatementWalker += StrLen (StatementWalker) + 1;\r
a405b86d 483 } else {\r
47d20b54 484 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");\r
a405b86d 485 Status = EFI_INVALID_PARAMETER;\r
486 }\r
487 } else {\r
47d20b54 488 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");\r
a405b86d 489 Status = EFI_INVALID_PARAMETER;\r
490 }\r
47d20b54
MK
491 } else if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"pierror", &Match)) && Match) {\r
492 TempSpot = StrStr (StatementWalker, L")");\r
493 if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"(", &Match)) && Match && (TempSpot != NULL)) {\r
a405b86d 494 *TempSpot = CHAR_NULL;\r
47d20b54
MK
495 if (ShellIsHexOrDecimalNumber (StatementWalker, FALSE, FALSE)) {\r
496 UnicodeSPrint (HexString, sizeof (HexString), L"0x%x", ShellStrToUintn (StatementWalker)|MAX_BIT|(MAX_BIT>>2));\r
497 ASSERT (Compare1 == NULL);\r
498 Compare1 = StrnCatGrow (&Compare1, NULL, HexString, 0);\r
499 StatementWalker += StrLen (StatementWalker) + 1;\r
a405b86d 500 } else {\r
47d20b54 501 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");\r
a405b86d 502 Status = EFI_INVALID_PARAMETER;\r
503 }\r
504 } else {\r
47d20b54 505 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");\r
a405b86d 506 Status = EFI_INVALID_PARAMETER;\r
507 }\r
47d20b54
MK
508 } else if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"oemerror", &Match)) && Match) {\r
509 TempSpot = StrStr (StatementWalker, L")");\r
510 if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"(", &Match)) && Match && (TempSpot != NULL)) {\r
a405b86d 511 TempSpot = CHAR_NULL;\r
47d20b54
MK
512 if (ShellIsHexOrDecimalNumber (StatementWalker, FALSE, FALSE)) {\r
513 UnicodeSPrint (HexString, sizeof (HexString), L"0x%x", ShellStrToUintn (StatementWalker)|MAX_BIT|(MAX_BIT>>1));\r
514 ASSERT (Compare1 == NULL);\r
515 Compare1 = StrnCatGrow (&Compare1, NULL, HexString, 0);\r
516 StatementWalker += StrLen (StatementWalker) + 1;\r
a405b86d 517 } else {\r
47d20b54 518 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");\r
a405b86d 519 Status = EFI_INVALID_PARAMETER;\r
520 }\r
521 } else {\r
47d20b54 522 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");\r
a405b86d 523 Status = EFI_INVALID_PARAMETER;\r
524 }\r
525 } else {\r
47d20b54 526 ASSERT (Compare1 == NULL);\r
a405b86d 527 if (EndParameterNumber - StartParameterNumber > 2) {\r
47d20b54
MK
528 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_STARTING), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[StartParameterNumber+2]);\r
529 Status = EFI_INVALID_PARAMETER;\r
a405b86d 530 } else {\r
531 //\r
532 // must be a raw string\r
533 //\r
47d20b54 534 Compare1 = StrnCatGrow (&Compare1, NULL, StatementWalker, 0);\r
a405b86d 535 }\r
536 }\r
537\r
538 //\r
539 // get the operator\r
540 //\r
47d20b54 541 ASSERT (StartParameterNumber+1 < EndParameterNumber);\r
a405b86d 542 StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber+1];\r
47d20b54 543 if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"gt", &Match)) && Match) {\r
77dcec12 544 BinOp = OperatorGreaterThan;\r
47d20b54 545 } else if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"lt", &Match)) && Match) {\r
77dcec12 546 BinOp = OperatorLessThan;\r
47d20b54 547 } else if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"eq", &Match)) && Match) {\r
77dcec12 548 BinOp = OperatorEqual;\r
47d20b54 549 } else if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"ne", &Match)) && Match) {\r
77dcec12 550 BinOp = OperatorNotEqual;\r
47d20b54 551 } else if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"ge", &Match)) && Match) {\r
77dcec12 552 BinOp = OperatorGreatorOrEqual;\r
47d20b54 553 } else if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"le", &Match)) && Match) {\r
77dcec12 554 BinOp = OperatorLessOrEqual;\r
47d20b54 555 } else if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"==", &Match)) && Match) {\r
77dcec12 556 BinOp = OperatorEqual;\r
47d20b54 557 } else if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"ugt", &Match)) && Match) {\r
77dcec12 558 BinOp = OperatorUnisgnedGreaterThan;\r
47d20b54 559 } else if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"ult", &Match)) && Match) {\r
77dcec12 560 BinOp = OperatorUnsignedLessThan;\r
47d20b54 561 } else if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"uge", &Match)) && Match) {\r
77dcec12 562 BinOp = OperatorUnsignedGreaterOrEqual;\r
47d20b54 563 } else if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"ule", &Match)) && Match) {\r
77dcec12 564 BinOp = OperatorUnsignedLessOrEqual;\r
a405b86d 565 } else {\r
47d20b54 566 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_INVALID_BINOP), gShellLevel1HiiHandle, StatementWalker);\r
a405b86d 567 Status = EFI_INVALID_PARAMETER;\r
568 }\r
569\r
570 //\r
571 // get the second item\r
572 //\r
47d20b54 573 ASSERT (StartParameterNumber+2 <= EndParameterNumber);\r
a405b86d 574 StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber+2];\r
47d20b54
MK
575 if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"efierror", &Match)) && Match) {\r
576 TempSpot = StrStr (StatementWalker, L")");\r
577 if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"(", &Match)) && Match && (TempSpot != NULL)) {\r
a405b86d 578 TempSpot = CHAR_NULL;\r
47d20b54
MK
579 if (ShellIsHexOrDecimalNumber (StatementWalker, FALSE, FALSE)) {\r
580 UnicodeSPrint (HexString, sizeof (HexString), L"0x%x", ShellStrToUintn (StatementWalker)|MAX_BIT);\r
581 ASSERT (Compare2 == NULL);\r
582 Compare2 = StrnCatGrow (&Compare2, NULL, HexString, 0);\r
583 StatementWalker += StrLen (StatementWalker) + 1;\r
a405b86d 584 } else {\r
47d20b54 585 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");\r
a405b86d 586 Status = EFI_INVALID_PARAMETER;\r
587 }\r
588 } else {\r
47d20b54 589 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");\r
a405b86d 590 Status = EFI_INVALID_PARAMETER;\r
591 }\r
47d20b54
MK
592\r
593 //\r
594 // can this be collapsed into the above?\r
595 //\r
596 } else if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"pierror", &Match)) && Match) {\r
597 TempSpot = StrStr (StatementWalker, L")");\r
598 if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"(", &Match)) && Match && (TempSpot != NULL)) {\r
a405b86d 599 TempSpot = CHAR_NULL;\r
47d20b54
MK
600 if (ShellIsHexOrDecimalNumber (StatementWalker, FALSE, FALSE)) {\r
601 UnicodeSPrint (HexString, sizeof (HexString), L"0x%x", ShellStrToUintn (StatementWalker)|MAX_BIT|(MAX_BIT>>2));\r
602 ASSERT (Compare2 == NULL);\r
603 Compare2 = StrnCatGrow (&Compare2, NULL, HexString, 0);\r
604 StatementWalker += StrLen (StatementWalker) + 1;\r
a405b86d 605 } else {\r
47d20b54 606 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");\r
a405b86d 607 Status = EFI_INVALID_PARAMETER;\r
608 }\r
609 } else {\r
47d20b54 610 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");\r
a405b86d 611 Status = EFI_INVALID_PARAMETER;\r
612 }\r
47d20b54
MK
613 } else if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"oemerror", &Match)) && Match) {\r
614 TempSpot = StrStr (StatementWalker, L")");\r
615 if (!EFI_ERROR (IsNextFragment ((CONST CHAR16 **)(&StatementWalker), L"(", &Match)) && Match && (TempSpot != NULL)) {\r
a405b86d 616 TempSpot = CHAR_NULL;\r
47d20b54
MK
617 if (ShellIsHexOrDecimalNumber (StatementWalker, FALSE, FALSE)) {\r
618 UnicodeSPrint (HexString, sizeof (HexString), L"0x%x", ShellStrToUintn (StatementWalker)|MAX_BIT|(MAX_BIT>>1));\r
619 ASSERT (Compare2 == NULL);\r
620 Compare2 = StrnCatGrow (&Compare2, NULL, HexString, 0);\r
621 StatementWalker += StrLen (StatementWalker) + 1;\r
a405b86d 622 } else {\r
47d20b54 623 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");\r
a405b86d 624 Status = EFI_INVALID_PARAMETER;\r
625 }\r
626 } else {\r
47d20b54 627 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");\r
a405b86d 628 Status = EFI_INVALID_PARAMETER;\r
629 }\r
630 } else {\r
631 //\r
632 // must be a raw string\r
633 //\r
47d20b54
MK
634 ASSERT (Compare2 == NULL);\r
635 Compare2 = StrnCatGrow (&Compare2, NULL, StatementWalker, 0);\r
a405b86d 636 }\r
637\r
47d20b54
MK
638 if ((Compare1 != NULL) && (Compare2 != NULL) && (BinOp != OperatorMax)) {\r
639 OperationResult = TestOperation (Compare1, Compare2, BinOp, CaseInsensitive, ForceStringCompare);\r
a405b86d 640 }\r
641\r
47d20b54
MK
642 SHELL_FREE_NON_NULL (Compare1);\r
643 SHELL_FREE_NON_NULL (Compare2);\r
a405b86d 644 }\r
645\r
646 //\r
647 // done processing do result...\r
648 //\r
649\r
47d20b54 650 if (!EFI_ERROR (Status)) {\r
a405b86d 651 if (NotPresent) {\r
652 OperationResult = (BOOLEAN)(!OperationResult);\r
653 }\r
47d20b54
MK
654\r
655 switch (OperatorToUse) {\r
77dcec12 656 case EndTagOr:\r
a405b86d 657 *PassingState = (BOOLEAN)(*PassingState || OperationResult);\r
658 break;\r
77dcec12 659 case EndTagAnd:\r
a405b86d 660 *PassingState = (BOOLEAN)(*PassingState && OperationResult);\r
661 break;\r
77dcec12 662 case EndTagMax:\r
a405b86d 663 *PassingState = (BOOLEAN)(OperationResult);\r
664 break;\r
665 default:\r
47d20b54 666 ASSERT (FALSE);\r
a405b86d 667 }\r
668 }\r
47d20b54 669\r
a405b86d 670 return (Status);\r
671}\r
672\r
77dcec12 673/**\r
674 Break up the next part of the if statement (until the next 'and', 'or', or 'then').\r
675\r
676 @param[in] ParameterNumber The current parameter number.\r
ba0014b9 677 @param[out] EndParameter Upon successful return, will point to the\r
77dcec12 678 parameter to start the next iteration with.\r
ba0014b9 679 @param[out] EndTag Upon successful return, will point to the\r
77dcec12 680 type that was found at the end of this statement.\r
681\r
682 @retval TRUE A valid statement was found.\r
683 @retval FALSE A valid statement was not found.\r
684**/\r
a405b86d 685BOOLEAN\r
a405b86d 686BuildNextStatement (\r
687 IN UINTN ParameterNumber,\r
688 OUT UINTN *EndParameter,\r
689 OUT END_TAG_TYPE *EndTag\r
690 )\r
691{\r
77dcec12 692 *EndTag = EndTagMax;\r
a405b86d 693\r
47d20b54
MK
694 for (\r
695 ; ParameterNumber < gEfiShellParametersProtocol->Argc\r
696 ; ParameterNumber++\r
697 )\r
698 {\r
699 if (gUnicodeCollation->StriColl (\r
700 gUnicodeCollation,\r
701 gEfiShellParametersProtocol->Argv[ParameterNumber],\r
702 L"or"\r
703 ) == 0)\r
704 {\r
a405b86d 705 *EndParameter = ParameterNumber - 1;\r
47d20b54 706 *EndTag = EndTagOr;\r
a405b86d 707 break;\r
47d20b54
MK
708 } else if (gUnicodeCollation->StriColl (\r
709 gUnicodeCollation,\r
710 gEfiShellParametersProtocol->Argv[ParameterNumber],\r
711 L"and"\r
712 ) == 0)\r
713 {\r
a405b86d 714 *EndParameter = ParameterNumber - 1;\r
47d20b54 715 *EndTag = EndTagAnd;\r
a405b86d 716 break;\r
47d20b54
MK
717 } else if (gUnicodeCollation->StriColl (\r
718 gUnicodeCollation,\r
719 gEfiShellParametersProtocol->Argv[ParameterNumber],\r
720 L"then"\r
721 ) == 0)\r
722 {\r
a405b86d 723 *EndParameter = ParameterNumber - 1;\r
47d20b54 724 *EndTag = EndTagThen;\r
a405b86d 725 break;\r
726 }\r
727 }\r
47d20b54 728\r
77dcec12 729 if (*EndTag == EndTagMax) {\r
a405b86d 730 return (FALSE);\r
731 }\r
47d20b54 732\r
a405b86d 733 return (TRUE);\r
734}\r
735\r
77dcec12 736/**\r
737 Move the script file pointer to a different place in the script file.\r
738 This one is special since it handles the if/else/endif syntax.\r
739\r
740 @param[in] ScriptFile The script file from GetCurrnetScriptFile().\r
741\r
742 @retval TRUE The move target was found and the move was successful.\r
743 @retval FALSE Something went wrong.\r
744**/\r
a405b86d 745BOOLEAN\r
a405b86d 746MoveToTagSpecial (\r
47d20b54 747 IN SCRIPT_FILE *ScriptFile\r
a405b86d 748 )\r
749{\r
47d20b54
MK
750 SCRIPT_COMMAND_LIST *CommandNode;\r
751 BOOLEAN Found;\r
752 UINTN TargetCount;\r
753 CHAR16 *CommandName;\r
754 CHAR16 *CommandWalker;\r
755 CHAR16 *TempLocation;\r
a405b86d 756\r
47d20b54
MK
757 TargetCount = 1;\r
758 Found = FALSE;\r
a405b86d 759\r
760 if (ScriptFile == NULL) {\r
761 return FALSE;\r
762 }\r
763\r
47d20b54
MK
764 for (CommandNode = (SCRIPT_COMMAND_LIST *)GetNextNode (&ScriptFile->CommandList, &ScriptFile->CurrentCommand->Link), Found = FALSE\r
765 ; !IsNull (&ScriptFile->CommandList, &CommandNode->Link) && !Found\r
766 ; CommandNode = (SCRIPT_COMMAND_LIST *)GetNextNode (&ScriptFile->CommandList, &CommandNode->Link)\r
767 )\r
768 {\r
a405b86d 769 //\r
770 // get just the first part of the command line...\r
771 //\r
47d20b54
MK
772 CommandName = NULL;\r
773 CommandName = StrnCatGrow (&CommandName, NULL, CommandNode->Cl, 0);\r
532691c8 774 if (CommandName == NULL) {\r
775 continue;\r
776 }\r
47d20b54 777\r
a405b86d 778 CommandWalker = CommandName;\r
13acebbd
CP
779\r
780 //\r
781 // Skip leading spaces and tabs.\r
782 //\r
783 while ((CommandWalker[0] == L' ') || (CommandWalker[0] == L'\t')) {\r
a405b86d 784 CommandWalker++;\r
785 }\r
47d20b54
MK
786\r
787 TempLocation = StrStr (CommandWalker, L" ");\r
a405b86d 788\r
789 if (TempLocation != NULL) {\r
790 *TempLocation = CHAR_NULL;\r
791 }\r
792\r
793 //\r
794 // did we find a nested item ?\r
795 //\r
47d20b54
MK
796 if (gUnicodeCollation->StriColl (\r
797 gUnicodeCollation,\r
798 (CHAR16 *)CommandWalker,\r
799 L"If"\r
800 ) == 0)\r
801 {\r
a405b86d 802 TargetCount++;\r
47d20b54
MK
803 } else if ((TargetCount == 1) && (gUnicodeCollation->StriColl (\r
804 gUnicodeCollation,\r
805 (CHAR16 *)CommandWalker,\r
806 (CHAR16 *)L"else"\r
807 ) == 0))\r
808 {\r
a405b86d 809 //\r
810 // else can only decrement the last part... not an nested if\r
811 // hence the TargetCount compare added\r
812 //\r
813 TargetCount--;\r
47d20b54
MK
814 } else if (gUnicodeCollation->StriColl (\r
815 gUnicodeCollation,\r
816 (CHAR16 *)CommandWalker,\r
817 (CHAR16 *)L"endif"\r
818 ) == 0)\r
819 {\r
a405b86d 820 TargetCount--;\r
821 }\r
47d20b54 822\r
a405b86d 823 if (TargetCount == 0) {\r
47d20b54
MK
824 ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetNextNode (&ScriptFile->CommandList, &CommandNode->Link);\r
825 Found = TRUE;\r
a405b86d 826 }\r
827\r
828 //\r
829 // Free the memory for this loop...\r
830 //\r
47d20b54 831 SHELL_FREE_NON_NULL (CommandName);\r
a405b86d 832 }\r
47d20b54 833\r
a405b86d 834 return (Found);\r
835}\r
836\r
77dcec12 837/**\r
838 Deal with the result of the if operation.\r
839\r
840 @param[in] Result The result of the if.\r
841\r
842 @retval EFI_SUCCESS The operation was successful.\r
843 @retval EFI_NOT_FOUND The ending tag could not be found.\r
844**/\r
a405b86d 845EFI_STATUS\r
a405b86d 846PerformResultOperation (\r
47d20b54 847 IN CONST BOOLEAN Result\r
a405b86d 848 )\r
849{\r
47d20b54 850 if (Result || MoveToTagSpecial (ShellCommandGetCurrentScriptFile ())) {\r
a405b86d 851 return (EFI_SUCCESS);\r
852 }\r
47d20b54 853\r
a405b86d 854 return (EFI_NOT_FOUND);\r
855}\r
856\r
857/**\r
858 Function for 'if' command.\r
859\r
860 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
861 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
862**/\r
863SHELL_STATUS\r
864EFIAPI\r
865ShellCommandRunIf (\r
866 IN EFI_HANDLE ImageHandle,\r
867 IN EFI_SYSTEM_TABLE *SystemTable\r
868 )\r
869{\r
47d20b54
MK
870 EFI_STATUS Status;\r
871 SHELL_STATUS ShellStatus;\r
872 BOOLEAN CaseInsensitive;\r
873 BOOLEAN ForceString;\r
874 UINTN CurrentParameter;\r
875 UINTN EndParameter;\r
876 BOOLEAN CurrentValue;\r
877 END_TAG_TYPE Ending;\r
878 END_TAG_TYPE PreviousEnding;\r
879 SCRIPT_FILE *CurrentScriptFile;\r
880\r
881 Status = CommandInit ();\r
882 ASSERT_EFI_ERROR (Status);\r
883\r
884 if (!gEfiShellProtocol->BatchIsActive ()) {\r
885 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"if");\r
a405b86d 886 return (SHELL_UNSUPPORTED);\r
887 }\r
888\r
889 if (gEfiShellParametersProtocol->Argc < 3) {\r
47d20b54 890 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel1HiiHandle, L"if");\r
a405b86d 891 return (SHELL_INVALID_PARAMETER);\r
892 }\r
893\r
894 //\r
895 // Make sure that an End exists.\r
896 //\r
47d20b54
MK
897 CurrentScriptFile = ShellCommandGetCurrentScriptFile ();\r
898 if (!MoveToTag (GetNextNode, L"endif", L"if", NULL, CurrentScriptFile, TRUE, TRUE, FALSE)) {\r
899 ShellPrintHiiEx (\r
ba0014b9
LG
900 -1,\r
901 -1,\r
902 NULL,\r
903 STRING_TOKEN (STR_SYNTAX_NO_MATCHING),\r
904 gShellLevel1HiiHandle,\r
905 L"EndIf",\r
906 L"If",\r
47d20b54
MK
907 CurrentScriptFile != NULL\r
908 && CurrentScriptFile->CurrentCommand != NULL\r
909 ? CurrentScriptFile->CurrentCommand->Line : 0\r
910 );\r
a405b86d 911 return (SHELL_DEVICE_ERROR);\r
912 }\r
913\r
914 //\r
915 // initialize the shell lib (we must be in non-auto-init...)\r
916 //\r
47d20b54
MK
917 Status = ShellInitialize ();\r
918 ASSERT_EFI_ERROR (Status);\r
919\r
920 CurrentParameter = 1;\r
921 EndParameter = 0;\r
922\r
923 if ((gUnicodeCollation->StriColl (\r
924 gUnicodeCollation,\r
925 gEfiShellParametersProtocol->Argv[1],\r
926 L"/i"\r
927 ) == 0) ||\r
928 (gUnicodeCollation->StriColl (\r
929 gUnicodeCollation,\r
930 gEfiShellParametersProtocol->Argv[2],\r
931 L"/i"\r
932 ) == 0) ||\r
933 ((gEfiShellParametersProtocol->Argc > 3) && (gUnicodeCollation->StriColl (\r
934 gUnicodeCollation,\r
935 gEfiShellParametersProtocol->Argv[3],\r
936 L"/i"\r
937 ) == 0)))\r
938 {\r
a405b86d 939 CaseInsensitive = TRUE;\r
940 CurrentParameter++;\r
941 } else {\r
942 CaseInsensitive = FALSE;\r
943 }\r
47d20b54
MK
944\r
945 if ((gUnicodeCollation->StriColl (\r
946 gUnicodeCollation,\r
947 gEfiShellParametersProtocol->Argv[1],\r
948 L"/s"\r
949 ) == 0) ||\r
950 (gUnicodeCollation->StriColl (\r
951 gUnicodeCollation,\r
952 gEfiShellParametersProtocol->Argv[2],\r
953 L"/s"\r
954 ) == 0) ||\r
955 ((gEfiShellParametersProtocol->Argc > 3) && (gUnicodeCollation->StriColl (\r
956 gUnicodeCollation,\r
957 gEfiShellParametersProtocol->Argv[3],\r
958 L"/s"\r
959 ) == 0)))\r
960 {\r
961 ForceString = TRUE;\r
a405b86d 962 CurrentParameter++;\r
963 } else {\r
47d20b54 964 ForceString = FALSE;\r
a405b86d 965 }\r
966\r
77dcec12 967 for ( ShellStatus = SHELL_SUCCESS, CurrentValue = FALSE, Ending = EndTagMax\r
47d20b54
MK
968 ; CurrentParameter < gEfiShellParametersProtocol->Argc && ShellStatus == SHELL_SUCCESS\r
969 ; CurrentParameter++)\r
970 {\r
971 if (gUnicodeCollation->StriColl (\r
972 gUnicodeCollation,\r
973 gEfiShellParametersProtocol->Argv[CurrentParameter],\r
974 L"then"\r
975 ) == 0)\r
976 {\r
a405b86d 977 //\r
978 // we are at the then\r
979 //\r
980 if (CurrentParameter+1 != gEfiShellParametersProtocol->Argc) {\r
47d20b54 981 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_TEXT_AFTER_THEN), gShellLevel1HiiHandle, L"if");\r
a405b86d 982 ShellStatus = SHELL_INVALID_PARAMETER;\r
983 } else {\r
47d20b54
MK
984 Status = PerformResultOperation (CurrentValue);\r
985 if (EFI_ERROR (Status)) {\r
986 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_AFTER_BAD), gShellLevel1HiiHandle, L"if", gEfiShellParametersProtocol->Argv[CurrentParameter]);\r
a405b86d 987 ShellStatus = SHELL_INVALID_PARAMETER;\r
988 }\r
989 }\r
990 } else {\r
991 PreviousEnding = Ending;\r
992 //\r
993 // build up the next statement for analysis\r
994 //\r
47d20b54
MK
995 if (!BuildNextStatement (CurrentParameter, &EndParameter, &Ending)) {\r
996 CurrentScriptFile = ShellCommandGetCurrentScriptFile ();\r
997 ShellPrintHiiEx (\r
ba0014b9
LG
998 -1,\r
999 -1,\r
1000 NULL,\r
1001 STRING_TOKEN (STR_SYNTAX_NO_MATCHING),\r
1002 gShellLevel1HiiHandle,\r
1003 L"Then",\r
ae724571 1004 L"If",\r
47d20b54
MK
1005 CurrentScriptFile != NULL\r
1006 && CurrentScriptFile->CurrentCommand != NULL\r
1007 ? CurrentScriptFile->CurrentCommand->Line : 0\r
1008 );\r
a405b86d 1009 ShellStatus = SHELL_INVALID_PARAMETER;\r
1010 } else {\r
1011 //\r
1012 // Analyze the statement\r
1013 //\r
47d20b54
MK
1014 Status = ProcessStatement (&CurrentValue, CurrentParameter, EndParameter, PreviousEnding, CaseInsensitive, ForceString);\r
1015 if (EFI_ERROR (Status)) {\r
1016 // ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_STARTING), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[CurrentParameter]);\r
a405b86d 1017 ShellStatus = SHELL_INVALID_PARAMETER;\r
1018 } else {\r
1019 //\r
1020 // Optomize to get out of the loop early...\r
1021 //\r
47d20b54
MK
1022 if (((Ending == EndTagOr) && CurrentValue) || ((Ending == EndTagAnd) && !CurrentValue)) {\r
1023 Status = PerformResultOperation (CurrentValue);\r
1024 if (EFI_ERROR (Status)) {\r
1025 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_AFTER_BAD), gShellLevel1HiiHandle, L"if", gEfiShellParametersProtocol->Argv[CurrentParameter]);\r
a405b86d 1026 ShellStatus = SHELL_INVALID_PARAMETER;\r
1027 }\r
47d20b54 1028\r
a405b86d 1029 break;\r
1030 }\r
1031 }\r
1032 }\r
47d20b54
MK
1033\r
1034 if (ShellStatus == SHELL_SUCCESS) {\r
a405b86d 1035 CurrentParameter = EndParameter;\r
1036 //\r
1037 // Skip over the or or and parameter.\r
1038 //\r
47d20b54 1039 if ((Ending == EndTagOr) || (Ending == EndTagAnd)) {\r
a405b86d 1040 CurrentParameter++;\r
1041 }\r
1042 }\r
1043 }\r
1044 }\r
47d20b54 1045\r
a405b86d 1046 return (ShellStatus);\r
1047}\r
1048\r
1049/**\r
1050 Function for 'else' command.\r
1051\r
1052 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
1053 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
1054**/\r
1055SHELL_STATUS\r
1056EFIAPI\r
1057ShellCommandRunElse (\r
1058 IN EFI_HANDLE ImageHandle,\r
1059 IN EFI_SYSTEM_TABLE *SystemTable\r
1060 )\r
1061{\r
47d20b54
MK
1062 EFI_STATUS Status;\r
1063 SCRIPT_FILE *CurrentScriptFile;\r
4a7518d3
LE
1064\r
1065 Status = CommandInit ();\r
1066 ASSERT_EFI_ERROR (Status);\r
a405b86d 1067\r
1068 if (gEfiShellParametersProtocol->Argc > 1) {\r
47d20b54 1069 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle, L"if");\r
a405b86d 1070 return (SHELL_INVALID_PARAMETER);\r
1071 }\r
1072\r
47d20b54
MK
1073 if (!gEfiShellProtocol->BatchIsActive ()) {\r
1074 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"Else");\r
a405b86d 1075 return (SHELL_UNSUPPORTED);\r
1076 }\r
1077\r
47d20b54 1078 CurrentScriptFile = ShellCommandGetCurrentScriptFile ();\r
a405b86d 1079\r
47d20b54
MK
1080 if (!MoveToTag (GetPreviousNode, L"if", L"endif", NULL, CurrentScriptFile, FALSE, TRUE, FALSE)) {\r
1081 ShellPrintHiiEx (\r
ba0014b9
LG
1082 -1,\r
1083 -1,\r
1084 NULL,\r
1085 STRING_TOKEN (STR_SYNTAX_NO_MATCHING),\r
1086 gShellLevel1HiiHandle,\r
1087 L"If",\r
1088 L"Else",\r
47d20b54
MK
1089 CurrentScriptFile != NULL\r
1090 && CurrentScriptFile->CurrentCommand != NULL\r
1091 ? CurrentScriptFile->CurrentCommand->Line : 0\r
1092 );\r
a405b86d 1093 return (SHELL_DEVICE_ERROR);\r
1094 }\r
47d20b54
MK
1095\r
1096 if (!MoveToTag (GetPreviousNode, L"if", L"else", NULL, CurrentScriptFile, FALSE, TRUE, FALSE)) {\r
1097 ShellPrintHiiEx (\r
ba0014b9
LG
1098 -1,\r
1099 -1,\r
1100 NULL,\r
1101 STRING_TOKEN (STR_SYNTAX_NO_MATCHING),\r
1102 gShellLevel1HiiHandle,\r
1103 L"If",\r
1104 L"Else",\r
47d20b54
MK
1105 CurrentScriptFile != NULL\r
1106 && CurrentScriptFile->CurrentCommand != NULL\r
1107 ? CurrentScriptFile->CurrentCommand->Line : 0\r
1108 );\r
a405b86d 1109 return (SHELL_DEVICE_ERROR);\r
1110 }\r
1111\r
47d20b54
MK
1112 if (!MoveToTag (GetNextNode, L"endif", L"if", NULL, CurrentScriptFile, FALSE, FALSE, FALSE)) {\r
1113 ShellPrintHiiEx (\r
ba0014b9
LG
1114 -1,\r
1115 -1,\r
1116 NULL,\r
1117 STRING_TOKEN (STR_SYNTAX_NO_MATCHING),\r
1118 gShellLevel1HiiHandle,\r
1119 L"EndIf",\r
1120 "Else",\r
47d20b54
MK
1121 CurrentScriptFile != NULL\r
1122 && CurrentScriptFile->CurrentCommand != NULL\r
1123 ? CurrentScriptFile->CurrentCommand->Line : 0\r
1124 );\r
a405b86d 1125 return (SHELL_DEVICE_ERROR);\r
1126 }\r
1127\r
1128 return (SHELL_SUCCESS);\r
1129}\r
1130\r
1131/**\r
1132 Function for 'endif' command.\r
1133\r
1134 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
1135 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
1136**/\r
1137SHELL_STATUS\r
1138EFIAPI\r
1139ShellCommandRunEndIf (\r
1140 IN EFI_HANDLE ImageHandle,\r
1141 IN EFI_SYSTEM_TABLE *SystemTable\r
1142 )\r
1143{\r
47d20b54
MK
1144 EFI_STATUS Status;\r
1145 SCRIPT_FILE *CurrentScriptFile;\r
4a7518d3
LE
1146\r
1147 Status = CommandInit ();\r
1148 ASSERT_EFI_ERROR (Status);\r
a405b86d 1149\r
1150 if (gEfiShellParametersProtocol->Argc > 1) {\r
47d20b54 1151 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle, L"if");\r
a405b86d 1152 return (SHELL_INVALID_PARAMETER);\r
1153 }\r
1154\r
47d20b54
MK
1155 if (!gEfiShellProtocol->BatchIsActive ()) {\r
1156 ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"Endif");\r
a405b86d 1157 return (SHELL_UNSUPPORTED);\r
1158 }\r
1159\r
47d20b54
MK
1160 CurrentScriptFile = ShellCommandGetCurrentScriptFile ();\r
1161 if (!MoveToTag (GetPreviousNode, L"if", L"endif", NULL, CurrentScriptFile, FALSE, TRUE, FALSE)) {\r
1162 ShellPrintHiiEx (\r
ba0014b9
LG
1163 -1,\r
1164 -1,\r
1165 NULL,\r
1166 STRING_TOKEN (STR_SYNTAX_NO_MATCHING),\r
1167 gShellLevel1HiiHandle,\r
1168 L"If",\r
1169 L"EndIf",\r
47d20b54
MK
1170 CurrentScriptFile != NULL\r
1171 && CurrentScriptFile->CurrentCommand != NULL\r
1172 ? CurrentScriptFile->CurrentCommand->Line : 0\r
1173 );\r
a405b86d 1174 return (SHELL_DEVICE_ERROR);\r
1175 }\r
1176\r
1177 return (SHELL_SUCCESS);\r
1178}\r