]> git.proxmox.com Git - mirror_edk2.git/blob - ShellPkg/Library/UefiShellLevel1CommandsLib/If.c
3376329622e6f5c075220bfe43dbaa6b00e7fb5f
[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 }
306 ASSERT(FALSE);
307 return (FALSE);
308 }
309
310 EFI_STATUS
311 EFIAPI
312 ProcessStatement (
313 IN OUT BOOLEAN *PassingState,
314 IN UINTN StartParameterNumber,
315 IN UINTN EndParameterNumber,
316 IN CONST END_TAG_TYPE OperatorToUse,
317 IN CONST BOOLEAN CaseInsensitive,
318 IN CONST BOOLEAN ForceStringCompare
319 )
320 {
321 EFI_STATUS Status;
322 BOOLEAN OperationResult;
323 BOOLEAN NotPresent;
324 CHAR16 *StatementWalker;
325 BIN_OPERATOR_TYPE BinOp;
326 CHAR16 *Compare1;
327 CHAR16 *Compare2;
328 CHAR16 HexString[20];
329 CHAR16 *TempSpot;
330
331 ASSERT((END_TAG_TYPE)OperatorToUse != END_TAG_THEN);
332
333 Status = EFI_SUCCESS;
334 BinOp = OPERATOR_MAX;
335 OperationResult = FALSE;
336 StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber];
337 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"not")) {
338 NotPresent = TRUE;
339 StatementWalker = gEfiShellParametersProtocol->Argv[++StartParameterNumber];
340 } else {
341 NotPresent = FALSE;
342 }
343
344 //
345 // now check for 'boolfunc' operators
346 //
347 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"isint")) {
348 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && StatementWalker[StrLen(StatementWalker)-1] == L')') {
349 StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL;
350 OperationResult = ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE);
351 } else {
352 Status = EFI_INVALID_PARAMETER;
353 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"isint");
354 }
355 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"exists") || IsNextFragment((CONST CHAR16**)(&StatementWalker), L"exist")) {
356 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && StatementWalker[StrLen(StatementWalker)-1] == L')') {
357 StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL;
358 //
359 // is what remains a file in CWD???
360 //
361 OperationResult = (BOOLEAN)(ShellFileExists(StatementWalker)==EFI_SUCCESS);
362 } else if (StatementWalker[0] == CHAR_NULL && StartParameterNumber+1 == EndParameterNumber) {
363 OperationResult = (BOOLEAN)(ShellFileExists(gEfiShellParametersProtocol->Argv[++StartParameterNumber])==EFI_SUCCESS);
364 } else {
365 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"exist(s)");
366 Status = EFI_INVALID_PARAMETER;
367 }
368 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"available")) {
369 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && StatementWalker[StrLen(StatementWalker)-1] == L')') {
370 StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL;
371 //
372 // is what remains a file in the CWD or path???
373 //
374 OperationResult = (BOOLEAN)(ShellIsFileInPath(StatementWalker)==EFI_SUCCESS);
375 } else {
376 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"available");
377 Status = EFI_INVALID_PARAMETER;
378 }
379 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"profile")) {
380 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && StatementWalker[StrLen(StatementWalker)-1] == L')') {
381 //
382 // Chop off that ')'
383 //
384 StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL;
385 OperationResult = IsValidProfile(StatementWalker);
386 } else {
387 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"profile");
388 Status = EFI_INVALID_PARAMETER;
389 }
390 } else if (StartParameterNumber+1 >= EndParameterNumber) {
391 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[StartParameterNumber]);
392 Status = EFI_INVALID_PARAMETER;
393 } else {
394 //
395 // must be 'item binop item' style
396 //
397 Compare1 = NULL;
398 Compare2 = NULL;
399 BinOp = OPERATOR_MAX;
400
401 //
402 // get the first item
403 //
404 StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber];
405 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"efierror")) {
406 TempSpot = StrStr(StatementWalker, L")");
407 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) {
408 *TempSpot = CHAR_NULL;
409 if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
410 UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT);
411 ASSERT(Compare1 == NULL);
412 Compare1 = StrnCatGrow(&Compare1, NULL, HexString, 0);
413 StatementWalker += StrLen(StatementWalker) + 1;
414 } else {
415 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");
416 Status = EFI_INVALID_PARAMETER;
417 }
418 } else {
419 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");
420 Status = EFI_INVALID_PARAMETER;
421 }
422 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"pierror")) {
423 TempSpot = StrStr(StatementWalker, L")");
424 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) {
425 *TempSpot = CHAR_NULL;
426 if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
427 UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>2));
428 ASSERT(Compare1 == NULL);
429 Compare1 = StrnCatGrow(&Compare1, NULL, HexString, 0);
430 StatementWalker += StrLen(StatementWalker) + 1;
431 } else {
432 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");
433 Status = EFI_INVALID_PARAMETER;
434 }
435 } else {
436 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");
437 Status = EFI_INVALID_PARAMETER;
438 }
439 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"oemerror")) {
440 TempSpot = StrStr(StatementWalker, L")");
441 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) {
442 TempSpot = CHAR_NULL;
443 if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
444 UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>1));
445 ASSERT(Compare1 == NULL);
446 Compare1 = StrnCatGrow(&Compare1, NULL, HexString, 0);
447 StatementWalker += StrLen(StatementWalker) + 1;
448 } else {
449 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");
450 Status = EFI_INVALID_PARAMETER;
451 }
452 } else {
453 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");
454 Status = EFI_INVALID_PARAMETER;
455 }
456 } else {
457 ASSERT(Compare1 == NULL);
458 if (EndParameterNumber - StartParameterNumber > 2) {
459 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_STARTING), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[StartParameterNumber+2]);
460 Status = EFI_INVALID_PARAMETER;
461 } else {
462 //
463 // must be a raw string
464 //
465 Compare1 = StrnCatGrow(&Compare1, NULL, StatementWalker, 0);
466 }
467 }
468
469 //
470 // get the operator
471 //
472 ASSERT(StartParameterNumber+1<EndParameterNumber);
473 StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber+1];
474 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"gt")) {
475 BinOp = OPERATOR_GT;
476 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"lt")) {
477 BinOp = OPERATOR_LT;
478 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"eq")) {
479 BinOp = OPERATOR_EQ;
480 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ne")) {
481 BinOp = OPERATOR_NE;
482 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ge")) {
483 BinOp = OPERATOR_GE;
484 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"le")) {
485 BinOp = OPERATOR_LE;
486 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"==")) {
487 BinOp = OPERATOR_EQ;
488 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ugt")) {
489 BinOp = OPERATOR_UGT;
490 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ult")) {
491 BinOp = OPERATOR_ULT;
492 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"uge")) {
493 BinOp = OPERATOR_UGE;
494 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ule")) {
495 BinOp = OPERATOR_ULE;
496 } else {
497 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_INVALID_BINOP), gShellLevel1HiiHandle, StatementWalker);
498 Status = EFI_INVALID_PARAMETER;
499 }
500
501 //
502 // get the second item
503 //
504 ASSERT(StartParameterNumber+2<=EndParameterNumber);
505 StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber+2];
506 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"efierror")) {
507 TempSpot = StrStr(StatementWalker, L")");
508 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) {
509 TempSpot = CHAR_NULL;
510 if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
511 UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT);
512 ASSERT(Compare2 == NULL);
513 Compare2 = StrnCatGrow(&Compare2, NULL, HexString, 0);
514 StatementWalker += StrLen(StatementWalker) + 1;
515 } else {
516 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");
517 Status = EFI_INVALID_PARAMETER;
518 }
519 } else {
520 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");
521 Status = EFI_INVALID_PARAMETER;
522 }
523 //
524 // can this be collapsed into the above?
525 //
526 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"pierror")) {
527 TempSpot = StrStr(StatementWalker, L")");
528 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) {
529 TempSpot = CHAR_NULL;
530 if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
531 UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>2));
532 ASSERT(Compare2 == NULL);
533 Compare2 = StrnCatGrow(&Compare2, NULL, HexString, 0);
534 StatementWalker += StrLen(StatementWalker) + 1;
535 } else {
536 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");
537 Status = EFI_INVALID_PARAMETER;
538 }
539 } else {
540 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");
541 Status = EFI_INVALID_PARAMETER;
542 }
543 } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"oemerror")) {
544 TempSpot = StrStr(StatementWalker, L")");
545 if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) {
546 TempSpot = CHAR_NULL;
547 if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
548 UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>1));
549 ASSERT(Compare2 == NULL);
550 Compare2 = StrnCatGrow(&Compare2, NULL, HexString, 0);
551 StatementWalker += StrLen(StatementWalker) + 1;
552 } else {
553 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");
554 Status = EFI_INVALID_PARAMETER;
555 }
556 } else {
557 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");
558 Status = EFI_INVALID_PARAMETER;
559 }
560 } else {
561 //
562 // must be a raw string
563 //
564 ASSERT(Compare2 == NULL);
565 Compare2 = StrnCatGrow(&Compare2, NULL, StatementWalker, 0);
566 }
567
568 if (Compare1 != NULL && Compare2 != NULL && BinOp != OPERATOR_MAX) {
569 OperationResult = TestOperation(Compare1, Compare2, BinOp, CaseInsensitive, ForceStringCompare);
570 }
571
572 SHELL_FREE_NON_NULL(Compare1);
573 SHELL_FREE_NON_NULL(Compare2);
574 }
575
576 //
577 // done processing do result...
578 //
579
580 if (!EFI_ERROR(Status)) {
581 if (NotPresent) {
582 OperationResult = (BOOLEAN)(!OperationResult);
583 }
584 switch(OperatorToUse) {
585 case END_TAG_OR:
586 *PassingState = (BOOLEAN)(*PassingState || OperationResult);
587 break;
588 case END_TAG_AND:
589 *PassingState = (BOOLEAN)(*PassingState && OperationResult);
590 break;
591 case END_TAG_MAX:
592 *PassingState = (BOOLEAN)(OperationResult);
593 break;
594 default:
595 ASSERT(FALSE);
596 }
597 }
598 return (Status);
599 }
600
601 BOOLEAN
602 EFIAPI
603 BuildNextStatement (
604 IN UINTN ParameterNumber,
605 OUT UINTN *EndParameter,
606 OUT END_TAG_TYPE *EndTag
607 )
608 {
609 CHAR16 *Buffer;
610 UINTN BufferSize;
611
612 *EndTag = END_TAG_MAX;
613
614 for(Buffer = NULL, BufferSize = 0
615 ; ParameterNumber < gEfiShellParametersProtocol->Argc
616 ; ParameterNumber++
617 ) {
618 if (gUnicodeCollation->StriColl(
619 gUnicodeCollation,
620 gEfiShellParametersProtocol->Argv[ParameterNumber],
621 L"or") == 0) {
622 *EndParameter = ParameterNumber - 1;
623 *EndTag = END_TAG_OR;
624 break;
625 } else if (gUnicodeCollation->StriColl(
626 gUnicodeCollation,
627 gEfiShellParametersProtocol->Argv[ParameterNumber],
628 L"and") == 0) {
629 *EndParameter = ParameterNumber - 1;
630 *EndTag = END_TAG_AND;
631 break;
632 } else if (gUnicodeCollation->StriColl(
633 gUnicodeCollation,
634 gEfiShellParametersProtocol->Argv[ParameterNumber],
635 L"then") == 0) {
636 *EndParameter = ParameterNumber - 1;
637 *EndTag = END_TAG_THEN;
638 break;
639 }
640 }
641 if (*EndTag == END_TAG_MAX) {
642 return (FALSE);
643 }
644 return (TRUE);
645 }
646
647 BOOLEAN
648 EFIAPI
649 MoveToTagSpecial (
650 IN SCRIPT_FILE *ScriptFile
651 )
652 {
653 SCRIPT_COMMAND_LIST *CommandNode;
654 BOOLEAN Found;
655 UINTN TargetCount;
656 CHAR16 *CommandName;
657 CHAR16 *CommandWalker;
658 CHAR16 *TempLocation;
659
660 TargetCount = 1;
661 Found = FALSE;
662
663 if (ScriptFile == NULL) {
664 return FALSE;
665 }
666
667 for (CommandNode = (SCRIPT_COMMAND_LIST *)GetNextNode(&ScriptFile->CommandList, &ScriptFile->CurrentCommand->Link), Found = FALSE
668 ; !IsNull(&ScriptFile->CommandList, &CommandNode->Link) && !Found
669 ; CommandNode = (SCRIPT_COMMAND_LIST *)GetNextNode(&ScriptFile->CommandList, &CommandNode->Link)
670 ){
671
672 //
673 // get just the first part of the command line...
674 //
675 CommandName = NULL;
676 CommandName = StrnCatGrow(&CommandName, NULL, CommandNode->Cl, 0);
677 CommandWalker = CommandName;
678 while (CommandWalker[0] == L' ') {
679 CommandWalker++;
680 }
681 TempLocation = StrStr(CommandWalker, L" ");
682
683 if (TempLocation != NULL) {
684 *TempLocation = CHAR_NULL;
685 }
686
687 //
688 // did we find a nested item ?
689 //
690 if (gUnicodeCollation->StriColl(
691 gUnicodeCollation,
692 (CHAR16*)CommandWalker,
693 L"If") == 0) {
694 TargetCount++;
695 } else if (TargetCount == 1 && gUnicodeCollation->StriColl(
696 gUnicodeCollation,
697 (CHAR16*)CommandWalker,
698 (CHAR16*)L"else") == 0) {
699 //
700 // else can only decrement the last part... not an nested if
701 // hence the TargetCount compare added
702 //
703 TargetCount--;
704 } else if (gUnicodeCollation->StriColl(
705 gUnicodeCollation,
706 (CHAR16*)CommandWalker,
707 (CHAR16*)L"endif") == 0) {
708 TargetCount--;
709 }
710 if (TargetCount == 0) {
711 ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetNextNode(&ScriptFile->CommandList, &CommandNode->Link);
712 Found = TRUE;
713 }
714
715 //
716 // Free the memory for this loop...
717 //
718 SHELL_FREE_NON_NULL(CommandName);
719 }
720 return (Found);
721 }
722
723 EFI_STATUS
724 EFIAPI
725 PerformResultOperation (
726 IN CONST BOOLEAN Result
727 )
728 {
729 if (Result || MoveToTagSpecial(ShellCommandGetCurrentScriptFile())) {
730 return (EFI_SUCCESS);
731 }
732 return (EFI_NOT_FOUND);
733 }
734
735 /**
736 Function for 'if' command.
737
738 @param[in] ImageHandle Handle to the Image (NULL if Internal).
739 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
740 **/
741 SHELL_STATUS
742 EFIAPI
743 ShellCommandRunIf (
744 IN EFI_HANDLE ImageHandle,
745 IN EFI_SYSTEM_TABLE *SystemTable
746 )
747 {
748 EFI_STATUS Status;
749 SHELL_STATUS ShellStatus;
750 BOOLEAN CaseInsensitive;
751 BOOLEAN ForceString;
752 UINTN CurrentParameter;
753 UINTN EndParameter;
754 BOOLEAN CurrentValue;
755 END_TAG_TYPE Ending;
756 END_TAG_TYPE PreviousEnding;
757
758
759 Status = CommandInit();
760 ASSERT_EFI_ERROR(Status);
761
762 if (!gEfiShellProtocol->BatchIsActive()) {
763 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"If");
764 return (SHELL_UNSUPPORTED);
765 }
766
767 if (gEfiShellParametersProtocol->Argc < 3) {
768 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel1HiiHandle);
769 return (SHELL_INVALID_PARAMETER);
770 }
771
772 //
773 // Make sure that an End exists.
774 //
775 if (!MoveToTag(GetNextNode, L"endif", L"if", NULL, ShellCommandGetCurrentScriptFile(), TRUE, TRUE, FALSE)) {
776 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"EnfIf", L"If", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);
777 return (SHELL_DEVICE_ERROR);
778 }
779
780 //
781 // initialize the shell lib (we must be in non-auto-init...)
782 //
783 Status = ShellInitialize();
784 ASSERT_EFI_ERROR(Status);
785
786 CurrentParameter = 1;
787 EndParameter = 0;
788
789 if (gUnicodeCollation->StriColl(
790 gUnicodeCollation,
791 gEfiShellParametersProtocol->Argv[1],
792 L"/i") == 0 ||
793 gUnicodeCollation->StriColl(
794 gUnicodeCollation,
795 gEfiShellParametersProtocol->Argv[2],
796 L"/i") == 0 ||
797 (gEfiShellParametersProtocol->Argc > 3 && gUnicodeCollation->StriColl(
798 gUnicodeCollation,
799 gEfiShellParametersProtocol->Argv[3],
800 L"/i") == 0)) {
801 CaseInsensitive = TRUE;
802 CurrentParameter++;
803 } else {
804 CaseInsensitive = FALSE;
805 }
806 if (gUnicodeCollation->StriColl(
807 gUnicodeCollation,
808 gEfiShellParametersProtocol->Argv[1],
809 L"/s") == 0 ||
810 gUnicodeCollation->StriColl(
811 gUnicodeCollation,
812 gEfiShellParametersProtocol->Argv[2],
813 L"/s") == 0 ||
814 (gEfiShellParametersProtocol->Argc > 3 && gUnicodeCollation->StriColl(
815 gUnicodeCollation,
816 gEfiShellParametersProtocol->Argv[3],
817 L"/s") == 0)) {
818 ForceString = TRUE;
819 CurrentParameter++;
820 } else {
821 ForceString = FALSE;
822 }
823
824 for ( ShellStatus = SHELL_SUCCESS, CurrentValue = FALSE, Ending = END_TAG_MAX
825 ; CurrentParameter < gEfiShellParametersProtocol->Argc && ShellStatus == SHELL_SUCCESS
826 ; CurrentParameter++) {
827 if (gUnicodeCollation->StriColl(
828 gUnicodeCollation,
829 gEfiShellParametersProtocol->Argv[CurrentParameter],
830 L"then") == 0) {
831 //
832 // we are at the then
833 //
834 if (CurrentParameter+1 != gEfiShellParametersProtocol->Argc) {
835 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TEXT_AFTER_THEN), gShellLevel1HiiHandle);
836 ShellStatus = SHELL_INVALID_PARAMETER;
837 } else {
838 Status = PerformResultOperation(CurrentValue);
839 if (EFI_ERROR(Status)) {
840 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_AFTER_BAD), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[CurrentParameter]);
841 ShellStatus = SHELL_INVALID_PARAMETER;
842 }
843 }
844 } else {
845 PreviousEnding = Ending;
846 //
847 // build up the next statement for analysis
848 //
849 if (!BuildNextStatement(CurrentParameter, &EndParameter, &Ending)) {
850 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"Then", L"If", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);
851 ShellStatus = SHELL_INVALID_PARAMETER;
852 } else {
853 //
854 // Analyze the statement
855 //
856 Status = ProcessStatement(&CurrentValue, CurrentParameter, EndParameter, PreviousEnding, CaseInsensitive, ForceString);
857 if (EFI_ERROR(Status)) {
858 // ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_STARTING), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[CurrentParameter]);
859 ShellStatus = SHELL_INVALID_PARAMETER;
860 } else {
861 //
862 // Optomize to get out of the loop early...
863 //
864 if ((Ending == END_TAG_OR && CurrentValue) || (Ending == END_TAG_AND && !CurrentValue)) {
865 Status = PerformResultOperation(CurrentValue);
866 if (EFI_ERROR(Status)) {
867 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_AFTER_BAD), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[CurrentParameter]);
868 ShellStatus = SHELL_INVALID_PARAMETER;
869 }
870 break;
871 }
872 }
873 }
874 if (ShellStatus == SHELL_SUCCESS){
875 CurrentParameter = EndParameter;
876 //
877 // Skip over the or or and parameter.
878 //
879 if (Ending == END_TAG_OR || Ending == END_TAG_AND) {
880 CurrentParameter++;
881 }
882 }
883 }
884 }
885 return (ShellStatus);
886 }
887
888 /**
889 Function for 'else' command.
890
891 @param[in] ImageHandle Handle to the Image (NULL if Internal).
892 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
893 **/
894 SHELL_STATUS
895 EFIAPI
896 ShellCommandRunElse (
897 IN EFI_HANDLE ImageHandle,
898 IN EFI_SYSTEM_TABLE *SystemTable
899 )
900 {
901 ASSERT_EFI_ERROR(CommandInit());
902
903 if (gEfiShellParametersProtocol->Argc > 1) {
904 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle);
905 return (SHELL_INVALID_PARAMETER);
906 }
907
908 if (!gEfiShellProtocol->BatchIsActive()) {
909 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"Else");
910 return (SHELL_UNSUPPORTED);
911 }
912
913
914 if (!MoveToTag(GetPreviousNode, L"if", L"endif", NULL, ShellCommandGetCurrentScriptFile(), FALSE, TRUE, FALSE)) {
915 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"If", L"Else", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);
916 return (SHELL_DEVICE_ERROR);
917 }
918 if (!MoveToTag(GetPreviousNode, L"if", L"else", NULL, ShellCommandGetCurrentScriptFile(), FALSE, TRUE, FALSE)) {
919 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"If", L"Else", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);
920 return (SHELL_DEVICE_ERROR);
921 }
922
923 if (!MoveToTag(GetNextNode, L"endif", L"if", NULL, ShellCommandGetCurrentScriptFile(), FALSE, FALSE, FALSE)) {
924 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"EndIf", "Else", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);
925 return (SHELL_DEVICE_ERROR);
926 }
927
928 return (SHELL_SUCCESS);
929 }
930
931 /**
932 Function for 'endif' command.
933
934 @param[in] ImageHandle Handle to the Image (NULL if Internal).
935 @param[in] SystemTable Pointer to the System Table (NULL if Internal).
936 **/
937 SHELL_STATUS
938 EFIAPI
939 ShellCommandRunEndIf (
940 IN EFI_HANDLE ImageHandle,
941 IN EFI_SYSTEM_TABLE *SystemTable
942 )
943 {
944 ASSERT_EFI_ERROR(CommandInit());
945
946 if (gEfiShellParametersProtocol->Argc > 1) {
947 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle);
948 return (SHELL_INVALID_PARAMETER);
949 }
950
951 if (!gEfiShellProtocol->BatchIsActive()) {
952 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"Endif");
953 return (SHELL_UNSUPPORTED);
954 }
955
956 if (!MoveToTag(GetPreviousNode, L"if", L"endif", NULL, ShellCommandGetCurrentScriptFile(), FALSE, TRUE, FALSE)) {
957 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"If", L"EndIf", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);
958 return (SHELL_DEVICE_ERROR);
959 }
960
961 return (SHELL_SUCCESS);
962 }