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