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