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