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