]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellLevel1CommandsLib/For.c
ShellPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / ShellPkg / Library / UefiShellLevel1CommandsLib / For.c
CommitLineData
a405b86d 1/** @file\r
2 Main file for endfor and for shell level 1 functions.\r
3\r
c011b6c9 4 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>\r
7162fdb0 5 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
56ba3746 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
a405b86d 7\r
8**/\r
9\r
10#include "UefiShellLevel1CommandsLib.h"\r
11#include <Library/PrintLib.h>\r
12\r
77dcec12 13/**\r
14 Determine if a valid string is a valid number for the 'for' command.\r
15\r
16 @param[in] Number The pointer to the string representation of the number to test.\r
17\r
18 @retval TRUE The number is valid.\r
19 @retval FALSE The number is not valid.\r
20**/\r
a405b86d 21BOOLEAN\r
a405b86d 22ShellIsValidForNumber (\r
23 IN CONST CHAR16 *Number\r
24 )\r
25{\r
26 if (Number == NULL || *Number == CHAR_NULL) {\r
27 return (FALSE);\r
28 }\r
29\r
30 if (*Number == L'-') {\r
31 Number++;\r
32 }\r
33\r
34 if (StrLen(Number) == 0) {\r
35 return (FALSE);\r
36 }\r
37\r
38 if (StrLen(Number) >= 7) {\r
2d3759d8 39 if ((StrStr(Number, L" ") == NULL) || (((StrStr(Number, L" ") != NULL) && (StrStr(Number, L" ") - Number) >= 7))) {\r
a405b86d 40 return (FALSE);\r
41 }\r
42 }\r
43\r
44 if (!ShellIsDecimalDigitCharacter(*Number)) {\r
45 return (FALSE);\r
46 }\r
47\r
48 return (TRUE);\r
49}\r
50\r
51/**\r
52 Function for 'endfor' command.\r
53\r
54 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
55 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
56**/\r
57SHELL_STATUS\r
58EFIAPI\r
59ShellCommandRunEndFor (\r
60 IN EFI_HANDLE ImageHandle,\r
61 IN EFI_SYSTEM_TABLE *SystemTable\r
62 )\r
63{\r
64 EFI_STATUS Status;\r
65 BOOLEAN Found;\r
ae724571 66 SCRIPT_FILE *CurrentScriptFile;\r
a405b86d 67\r
68 Status = CommandInit();\r
69 ASSERT_EFI_ERROR(Status);\r
70\r
71 if (!gEfiShellProtocol->BatchIsActive()) {\r
0861edab 72 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"endfor");\r
a405b86d 73 return (SHELL_UNSUPPORTED);\r
74 }\r
75\r
76 if (gEfiShellParametersProtocol->Argc > 1) {\r
0861edab 77 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle, L"endfor");\r
a405b86d 78 return (SHELL_INVALID_PARAMETER);\r
79 }\r
80\r
81 Found = MoveToTag(GetPreviousNode, L"for", L"endfor", NULL, ShellCommandGetCurrentScriptFile(), FALSE, FALSE, FALSE);\r
82\r
83 if (!Found) {\r
ae724571 84 CurrentScriptFile = ShellCommandGetCurrentScriptFile();\r
33c031ee 85 ShellPrintHiiEx(\r
ba0014b9
LG
86 -1,\r
87 -1,\r
88 NULL,\r
89 STRING_TOKEN (STR_SYNTAX_NO_MATCHING),\r
90 gShellLevel1HiiHandle,\r
91 L"For",\r
92 L"EndFor",\r
ae724571 93 CurrentScriptFile!=NULL\r
94 && CurrentScriptFile->CurrentCommand!=NULL\r
95 ? CurrentScriptFile->CurrentCommand->Line:0);\r
a405b86d 96 return (SHELL_NOT_FOUND);\r
97 }\r
98 return (SHELL_SUCCESS);\r
99}\r
100\r
101typedef struct {\r
102 UINT32 Signature;\r
103 INTN Current;\r
104 INTN End;\r
105 INTN Step;\r
106 CHAR16 *ReplacementName;\r
107 CHAR16 *CurrentValue;\r
108 BOOLEAN RemoveSubstAlias;\r
109 CHAR16 Set[1];\r
110 } SHELL_FOR_INFO;\r
111#define SIZE_OF_SHELL_FOR_INFO OFFSET_OF (SHELL_FOR_INFO, Set)\r
112#define SHELL_FOR_INFO_SIGNATURE SIGNATURE_32 ('S', 'F', 'I', 's')\r
113\r
114/**\r
115 Update the value of a given alias on the list. If the alias is not there then add it.\r
116\r
4ff7e37b
ED
117 @param[in] Alias The alias to test for.\r
118 @param[in] CommandString The updated command string.\r
119 @param[in, out] List The list to search.\r
9ea69f8a 120\r
121 @retval EFI_SUCCESS The operation was completed successfully.\r
122 @retval EFI_OUT_OF_RESOURCES There was not enough free memory.\r
a405b86d 123**/\r
9ea69f8a 124EFI_STATUS\r
a405b86d 125InternalUpdateAliasOnList(\r
126 IN CONST CHAR16 *Alias,\r
127 IN CONST CHAR16 *CommandString,\r
128 IN OUT LIST_ENTRY *List\r
129 )\r
130{\r
131 ALIAS_LIST *Node;\r
132 BOOLEAN Found;\r
133\r
134 //\r
135 // assert for NULL parameter\r
136 //\r
137 ASSERT(Alias != NULL);\r
138\r
139 //\r
140 // check for the Alias\r
141 //\r
142 for ( Node = (ALIAS_LIST *)GetFirstNode(List), Found = FALSE\r
143 ; !IsNull(List, &Node->Link)\r
144 ; Node = (ALIAS_LIST *)GetNextNode(List, &Node->Link)\r
145 ){\r
146 ASSERT(Node->CommandString != NULL);\r
147 ASSERT(Node->Alias != NULL);\r
148 if (StrCmp(Node->Alias, Alias)==0) {\r
149 FreePool(Node->CommandString);\r
150 Node->CommandString = NULL;\r
151 Node->CommandString = StrnCatGrow(&Node->CommandString, NULL, CommandString, 0);\r
152 Found = TRUE;\r
153 break;\r
154 }\r
155 }\r
156 if (!Found) {\r
157 Node = AllocateZeroPool(sizeof(ALIAS_LIST));\r
9ea69f8a 158 if (Node == NULL) {\r
159 return (EFI_OUT_OF_RESOURCES);\r
160 }\r
a405b86d 161 ASSERT(Node->Alias == NULL);\r
162 Node->Alias = StrnCatGrow(&Node->Alias, NULL, Alias, 0);\r
163 ASSERT(Node->CommandString == NULL);\r
164 Node->CommandString = StrnCatGrow(&Node->CommandString, NULL, CommandString, 0);\r
165 InsertTailList(List, &Node->Link);\r
166 }\r
9ea69f8a 167 return (EFI_SUCCESS);\r
a405b86d 168}\r
169\r
170/**\r
171 Find out if an alias is on the given list.\r
172\r
173 @param[in] Alias The alias to test for.\r
174 @param[in] List The list to search.\r
175\r
176 @retval TRUE The alias is on the list.\r
177 @retval FALSE The alias is not on the list.\r
178**/\r
179BOOLEAN\r
a405b86d 180InternalIsAliasOnList(\r
181 IN CONST CHAR16 *Alias,\r
182 IN CONST LIST_ENTRY *List\r
183 )\r
184{\r
185 ALIAS_LIST *Node;\r
186\r
187 //\r
188 // assert for NULL parameter\r
189 //\r
190 ASSERT(Alias != NULL);\r
191\r
192 //\r
193 // check for the Alias\r
194 //\r
195 for ( Node = (ALIAS_LIST *)GetFirstNode(List)\r
196 ; !IsNull(List, &Node->Link)\r
197 ; Node = (ALIAS_LIST *)GetNextNode(List, &Node->Link)\r
198 ){\r
199 ASSERT(Node->CommandString != NULL);\r
200 ASSERT(Node->Alias != NULL);\r
201 if (StrCmp(Node->Alias, Alias)==0) {\r
202 return (TRUE);\r
203 }\r
204 }\r
205 return (FALSE);\r
206}\r
207\r
208/**\r
209 Remove an alias from the given list.\r
210\r
4ff7e37b
ED
211 @param[in] Alias The alias to remove.\r
212 @param[in, out] List The list to search.\r
a405b86d 213**/\r
214BOOLEAN\r
a405b86d 215InternalRemoveAliasFromList(\r
216 IN CONST CHAR16 *Alias,\r
217 IN OUT LIST_ENTRY *List\r
218 )\r
219{\r
220 ALIAS_LIST *Node;\r
221\r
222 //\r
223 // assert for NULL parameter\r
224 //\r
225 ASSERT(Alias != NULL);\r
226\r
227 //\r
228 // check for the Alias\r
229 //\r
230 for ( Node = (ALIAS_LIST *)GetFirstNode(List)\r
231 ; !IsNull(List, &Node->Link)\r
232 ; Node = (ALIAS_LIST *)GetNextNode(List, &Node->Link)\r
233 ){\r
234 ASSERT(Node->CommandString != NULL);\r
235 ASSERT(Node->Alias != NULL);\r
236 if (StrCmp(Node->Alias, Alias)==0) {\r
237 RemoveEntryList(&Node->Link);\r
238 FreePool(Node->Alias);\r
239 FreePool(Node->CommandString);\r
240 FreePool(Node);\r
241 return (TRUE);\r
242 }\r
243 }\r
244 return (FALSE);\r
245}\r
246\r
e82edcf9
JC
247/**\r
248 Function to determine whether a string is decimal or hex representation of a number\r
249 and return the number converted from the string.\r
250\r
251 @param[in] String String representation of a number\r
252\r
253 @return the number\r
254 @retval (UINTN)(-1) An error ocurred.\r
255**/\r
256UINTN\r
e82edcf9
JC
257ReturnUintn(\r
258 IN CONST CHAR16 *String\r
259 )\r
260{\r
261 UINT64 RetVal;\r
262\r
c8186395 263 if (!EFI_ERROR(ShellConvertStringToUint64(String, &RetVal, FALSE, TRUE))) {\r
e82edcf9
JC
264 return ((UINTN)RetVal);\r
265 }\r
266 return ((UINTN)(-1));\r
267}\r
268\r
a405b86d 269/**\r
270 Function for 'for' command.\r
271\r
272 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
273 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
274**/\r
275SHELL_STATUS\r
276EFIAPI\r
277ShellCommandRunFor (\r
278 IN EFI_HANDLE ImageHandle,\r
279 IN EFI_SYSTEM_TABLE *SystemTable\r
280 )\r
281{\r
282 EFI_STATUS Status;\r
283 SHELL_STATUS ShellStatus;\r
284 SCRIPT_FILE *CurrentScriptFile;\r
285 CHAR16 *ArgSet;\r
286 CHAR16 *ArgSetWalker;\r
3a3395f0 287 CHAR16 *Parameter;\r
a405b86d 288 UINTN ArgSize;\r
289 UINTN LoopVar;\r
290 SHELL_FOR_INFO *Info;\r
291 CHAR16 *TempString;\r
292 CHAR16 *TempSpot;\r
293 BOOLEAN FirstPass;\r
294 EFI_SHELL_FILE_INFO *Node;\r
295 EFI_SHELL_FILE_INFO *FileList;\r
296 UINTN NewSize;\r
297\r
298 ArgSet = NULL;\r
299 ArgSize = 0;\r
300 ShellStatus = SHELL_SUCCESS;\r
301 ArgSetWalker = NULL;\r
302 TempString = NULL;\r
3a3395f0 303 Parameter = NULL;\r
a405b86d 304 FirstPass = FALSE;\r
305\r
306 //\r
307 // initialize the shell lib (we must be in non-auto-init...)\r
308 //\r
309 Status = ShellInitialize();\r
310 ASSERT_EFI_ERROR(Status);\r
311\r
312 Status = CommandInit();\r
313 ASSERT_EFI_ERROR(Status);\r
314\r
315 if (!gEfiShellProtocol->BatchIsActive()) {\r
0861edab 316 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"for");\r
a405b86d 317 return (SHELL_UNSUPPORTED);\r
318 }\r
319\r
320 if (gEfiShellParametersProtocol->Argc < 4) {\r
0861edab 321 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel1HiiHandle, L"for");\r
a405b86d 322 return (SHELL_INVALID_PARAMETER);\r
323 }\r
324\r
325 CurrentScriptFile = ShellCommandGetCurrentScriptFile();\r
326 ASSERT(CurrentScriptFile != NULL);\r
327\r
81cd2f53 328 if ((CurrentScriptFile->CurrentCommand != NULL) && (CurrentScriptFile->CurrentCommand->Data == NULL)) {\r
a405b86d 329 FirstPass = TRUE;\r
330\r
331 //\r
332 // Make sure that an End exists.\r
333 //\r
334 if (!MoveToTag(GetNextNode, L"endfor", L"for", NULL, CurrentScriptFile, TRUE, TRUE, FALSE)) {\r
33c031ee 335 ShellPrintHiiEx(\r
ba0014b9
LG
336 -1,\r
337 -1,\r
338 NULL,\r
339 STRING_TOKEN (STR_SYNTAX_NO_MATCHING),\r
340 gShellLevel1HiiHandle,\r
341 L"EndFor",\r
342 L"For",\r
81cd2f53 343 CurrentScriptFile->CurrentCommand->Line);\r
a405b86d 344 return (SHELL_DEVICE_ERROR);\r
345 }\r
346\r
347 //\r
348 // Process the line.\r
349 //\r
350 if (gEfiShellParametersProtocol->Argv[1][0] != L'%' || gEfiShellParametersProtocol->Argv[1][2] != CHAR_NULL\r
351 ||!((gEfiShellParametersProtocol->Argv[1][1] >= L'a' && gEfiShellParametersProtocol->Argv[1][1] <= L'z')\r
352 ||(gEfiShellParametersProtocol->Argv[1][1] >= L'A' && gEfiShellParametersProtocol->Argv[1][1] <= L'Z'))\r
353 ) {\r
77dcec12 354 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_VAR), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[1]);\r
a405b86d 355 return (SHELL_INVALID_PARAMETER);\r
356 }\r
357\r
358 if (gUnicodeCollation->StriColl(\r
359 gUnicodeCollation,\r
360 L"in",\r
361 gEfiShellParametersProtocol->Argv[2]) == 0) {\r
362 for (LoopVar = 0x3 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) {\r
363 ASSERT((ArgSet == NULL && ArgSize == 0) || (ArgSet != NULL));\r
a405b86d 364 if (StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"*") != NULL\r
365 ||StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"?") != NULL\r
366 ||StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"[") != NULL\r
367 ||StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"]") != NULL) {\r
368 FileList = NULL;\r
369 Status = ShellOpenFileMetaArg ((CHAR16*)gEfiShellParametersProtocol->Argv[LoopVar], EFI_FILE_MODE_READ, &FileList);\r
370 if (EFI_ERROR(Status) || FileList == NULL || IsListEmpty(&FileList->Link)) {\r
5b056113 371 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" \"", 0);\r
a405b86d 372 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, gEfiShellParametersProtocol->Argv[LoopVar], 0);\r
5b056113 373 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0);\r
a405b86d 374 } else {\r
375 for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link)\r
376 ; !IsNull(&FileList->Link, &Node->Link)\r
377 ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link)\r
378 ){\r
379 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" \"", 0);\r
380 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, Node->FullName, 0);\r
381 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0);\r
382 }\r
383 ShellCloseFileMetaArg(&FileList);\r
384 }\r
385 } else {\r
3a3395f0
QS
386 Parameter = gEfiShellParametersProtocol->Argv[LoopVar];\r
387 if (Parameter[0] == L'\"' && Parameter[StrLen(Parameter)-1] == L'\"') {\r
388 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" ", 0);\r
389 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, Parameter, 0);\r
390 } else {\r
391 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" \"", 0);\r
392 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, Parameter, 0);\r
393 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0);\r
394 }\r
a405b86d 395 }\r
a405b86d 396 }\r
532691c8 397 if (ArgSet == NULL) {\r
398 ShellStatus = SHELL_OUT_OF_RESOURCES;\r
a405b86d 399 } else {\r
532691c8 400 //\r
401 // set up for an 'in' for loop\r
402 //\r
403 NewSize = StrSize(ArgSet);\r
404 NewSize += sizeof(SHELL_FOR_INFO)+StrSize(gEfiShellParametersProtocol->Argv[1]);\r
405 Info = AllocateZeroPool(NewSize);\r
59b7dbac
RN
406 if (Info == NULL) {\r
407 FreePool (ArgSet);\r
408 return SHELL_OUT_OF_RESOURCES;\r
409 }\r
532691c8 410 Info->Signature = SHELL_FOR_INFO_SIGNATURE;\r
411 CopyMem(Info->Set, ArgSet, StrSize(ArgSet));\r
412 NewSize = StrSize(gEfiShellParametersProtocol->Argv[1]);\r
413 CopyMem(Info->Set+(StrSize(ArgSet)/sizeof(Info->Set[0])), gEfiShellParametersProtocol->Argv[1], NewSize);\r
414 Info->ReplacementName = Info->Set+StrSize(ArgSet)/sizeof(Info->Set[0]);\r
415 Info->CurrentValue = (CHAR16*)Info->Set;\r
416 Info->Step = 0;\r
417 Info->Current = 0;\r
418 Info->End = 0;\r
419\r
420 if (InternalIsAliasOnList(Info->ReplacementName, &CurrentScriptFile->SubstList)) {\r
421 Info->RemoveSubstAlias = FALSE;\r
422 } else {\r
423 Info->RemoveSubstAlias = TRUE;\r
424 }\r
425 CurrentScriptFile->CurrentCommand->Data = Info;\r
a405b86d 426 }\r
a405b86d 427 } else if (gUnicodeCollation->StriColl(\r
428 gUnicodeCollation,\r
429 L"run",\r
430 gEfiShellParametersProtocol->Argv[2]) == 0) {\r
431 for (LoopVar = 0x3 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) {\r
432 ASSERT((ArgSet == NULL && ArgSize == 0) || (ArgSet != NULL));\r
8337590c
QS
433 if (StrStr (gEfiShellParametersProtocol->Argv[LoopVar], L")") != NULL &&\r
434 (LoopVar + 1) < gEfiShellParametersProtocol->Argc\r
435 ) {\r
436 return (SHELL_INVALID_PARAMETER);\r
437 }\r
a405b86d 438 if (ArgSet == NULL) {\r
439// ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0);\r
440 } else {\r
77dcec12 441 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" ", 0);\r
a405b86d 442 }\r
443 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, gEfiShellParametersProtocol->Argv[LoopVar], 0);\r
444// ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" ", 0);\r
445 }\r
532691c8 446 if (ArgSet == NULL) {\r
447 ShellStatus = SHELL_OUT_OF_RESOURCES;\r
a405b86d 448 } else {\r
532691c8 449 //\r
450 // set up for a 'run' for loop\r
451 //\r
452 Info = AllocateZeroPool(sizeof(SHELL_FOR_INFO)+StrSize(gEfiShellParametersProtocol->Argv[1]));\r
59b7dbac
RN
453 if (Info == NULL) {\r
454 FreePool (ArgSet);\r
455 return SHELL_OUT_OF_RESOURCES;\r
456 }\r
b471606b 457 Info->Signature = SHELL_FOR_INFO_SIGNATURE;\r
532691c8 458 CopyMem(Info->Set, gEfiShellParametersProtocol->Argv[1], StrSize(gEfiShellParametersProtocol->Argv[1]));\r
459 Info->ReplacementName = Info->Set;\r
460 Info->CurrentValue = NULL;\r
461 ArgSetWalker = ArgSet;\r
462 if (ArgSetWalker[0] != L'(') {\r
ae724571 463 ShellPrintHiiEx(\r
ba0014b9
LG
464 -1,\r
465 -1,\r
466 NULL,\r
467 STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT),\r
468 gShellLevel1HiiHandle,\r
469 ArgSet,\r
81cd2f53 470 CurrentScriptFile->CurrentCommand->Line);\r
a405b86d 471 ShellStatus = SHELL_INVALID_PARAMETER;\r
472 } else {\r
532691c8 473 TempSpot = StrStr(ArgSetWalker, L")");\r
474 if (TempSpot != NULL) {\r
475 TempString = TempSpot+1;\r
476 if (*(TempString) != CHAR_NULL) {\r
477 while(TempString != NULL && *TempString == L' ') {\r
478 TempString++;\r
479 }\r
480 if (StrLen(TempString) > 0) {\r
481 TempSpot = NULL;\r
482 }\r
483 }\r
a405b86d 484 }\r
532691c8 485 if (TempSpot == NULL) {\r
ae724571 486 ShellPrintHiiEx(\r
ba0014b9
LG
487 -1,\r
488 -1,\r
489 NULL,\r
490 STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT),\r
491 gShellLevel1HiiHandle,\r
81cd2f53 492 CurrentScriptFile->CurrentCommand->Line);\r
a405b86d 493 ShellStatus = SHELL_INVALID_PARAMETER;\r
494 } else {\r
532691c8 495 *TempSpot = CHAR_NULL;\r
496 ArgSetWalker++;\r
a405b86d 497 while (ArgSetWalker != NULL && ArgSetWalker[0] == L' ') {\r
498 ArgSetWalker++;\r
499 }\r
532691c8 500 if (!ShellIsValidForNumber(ArgSetWalker)) {\r
ae724571 501 ShellPrintHiiEx(\r
ba0014b9
LG
502 -1,\r
503 -1,\r
504 NULL,\r
505 STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT),\r
506 gShellLevel1HiiHandle,\r
507 ArgSet,\r
81cd2f53 508 CurrentScriptFile->CurrentCommand->Line);\r
77dcec12 509 ShellStatus = SHELL_INVALID_PARAMETER;\r
510 } else {\r
511 if (ArgSetWalker[0] == L'-') {\r
e82edcf9 512 Info->Current = 0 - (INTN)ReturnUintn(ArgSetWalker+1);\r
77dcec12 513 } else {\r
e82edcf9 514 Info->Current = (INTN)ReturnUintn(ArgSetWalker);\r
77dcec12 515 }\r
77dcec12 516 ArgSetWalker = StrStr(ArgSetWalker, L" ");\r
517 while (ArgSetWalker != NULL && ArgSetWalker[0] == L' ') {\r
518 ArgSetWalker++;\r
519 }\r
532691c8 520 if (ArgSetWalker == NULL || *ArgSetWalker == CHAR_NULL || !ShellIsValidForNumber(ArgSetWalker)){\r
521 ShellPrintHiiEx(\r
ba0014b9
LG
522 -1,\r
523 -1,\r
524 NULL,\r
525 STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT),\r
526 gShellLevel1HiiHandle,\r
527 ArgSet,\r
81cd2f53 528 CurrentScriptFile->CurrentCommand->Line);\r
532691c8 529 ShellStatus = SHELL_INVALID_PARAMETER;\r
530 } else {\r
531 if (ArgSetWalker[0] == L'-') {\r
e82edcf9 532 Info->End = 0 - (INTN)ReturnUintn(ArgSetWalker+1);\r
a405b86d 533 } else {\r
e82edcf9 534 Info->End = (INTN)ReturnUintn(ArgSetWalker);\r
532691c8 535 }\r
536 if (Info->Current < Info->End) {\r
537 Info->Step = 1;\r
538 } else {\r
539 Info->Step = -1;\r
540 }\r
541\r
542 ArgSetWalker = StrStr(ArgSetWalker, L" ");\r
543 while (ArgSetWalker != NULL && ArgSetWalker[0] == L' ') {\r
544 ArgSetWalker++;\r
545 }\r
546 if (ArgSetWalker != NULL && *ArgSetWalker != CHAR_NULL) {\r
547 if (ArgSetWalker == NULL || *ArgSetWalker == CHAR_NULL || !ShellIsValidForNumber(ArgSetWalker)){\r
548 ShellPrintHiiEx(\r
ba0014b9
LG
549 -1,\r
550 -1,\r
551 NULL,\r
552 STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT),\r
553 gShellLevel1HiiHandle,\r
554 ArgSet,\r
81cd2f53 555 CurrentScriptFile->CurrentCommand->Line);\r
532691c8 556 ShellStatus = SHELL_INVALID_PARAMETER;\r
a405b86d 557 } else {\r
532691c8 558 if (*ArgSetWalker == L')') {\r
559 ASSERT(Info->Step == 1 || Info->Step == -1);\r
a405b86d 560 } else {\r
532691c8 561 if (ArgSetWalker[0] == L'-') {\r
e82edcf9 562 Info->Step = 0 - (INTN)ReturnUintn(ArgSetWalker+1);\r
532691c8 563 } else {\r
e82edcf9 564 Info->Step = (INTN)ReturnUintn(ArgSetWalker);\r
532691c8 565 }\r
566\r
567 if (StrStr(ArgSetWalker, L" ") != NULL) {\r
568 ShellPrintHiiEx(\r
ba0014b9
LG
569 -1,\r
570 -1,\r
571 NULL,\r
572 STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT),\r
573 gShellLevel1HiiHandle,\r
574 ArgSet,\r
81cd2f53 575 CurrentScriptFile->CurrentCommand->Line);\r
532691c8 576 ShellStatus = SHELL_INVALID_PARAMETER;\r
577 }\r
77dcec12 578 }\r
a405b86d 579 }\r
ba0014b9 580\r
a405b86d 581 }\r
582 }\r
583 }\r
584 }\r
585 }\r
532691c8 586 if (ShellStatus == SHELL_SUCCESS) {\r
587 if (InternalIsAliasOnList(Info->ReplacementName, &CurrentScriptFile->SubstList)) {\r
588 Info->RemoveSubstAlias = FALSE;\r
589 } else {\r
590 Info->RemoveSubstAlias = TRUE;\r
591 }\r
592 }\r
593 if (CurrentScriptFile->CurrentCommand != NULL) {\r
594 CurrentScriptFile->CurrentCommand->Data = Info;\r
a405b86d 595 }\r
cbdd109b 596 }\r
a405b86d 597 } else {\r
ae724571 598 ShellPrintHiiEx(\r
ba0014b9
LG
599 -1,\r
600 -1,\r
601 NULL,\r
602 STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT),\r
603 gShellLevel1HiiHandle,\r
604 ArgSet,\r
605 CurrentScriptFile!=NULL\r
ae724571 606 && CurrentScriptFile->CurrentCommand!=NULL\r
607 ? CurrentScriptFile->CurrentCommand->Line:0);\r
a405b86d 608 ShellStatus = SHELL_INVALID_PARAMETER;\r
609 }\r
610 } else {\r
611 //\r
612 // These need to be NULL since they are used to determine if this is the first pass later on...\r
613 //\r
614 ASSERT(ArgSetWalker == NULL);\r
615 ASSERT(ArgSet == NULL);\r
616 }\r
617\r
d8f8021c 618 if (CurrentScriptFile != NULL && CurrentScriptFile->CurrentCommand != NULL) {\r
619 Info = (SHELL_FOR_INFO*)CurrentScriptFile->CurrentCommand->Data;\r
620 if (CurrentScriptFile->CurrentCommand->Reset) {\r
7162fdb0
RN
621 if (Info != NULL) {\r
622 Info->CurrentValue = (CHAR16*)Info->Set;\r
623 }\r
d8f8021c 624 FirstPass = TRUE;\r
625 CurrentScriptFile->CurrentCommand->Reset = FALSE;\r
626 }\r
627 } else {\r
628 ShellStatus = SHELL_UNSUPPORTED;\r
629 Info = NULL;\r
a405b86d 630 }\r
631 if (ShellStatus == SHELL_SUCCESS) {\r
632 ASSERT(Info != NULL);\r
633 if (Info->Step != 0) {\r
634 //\r
635 // only advance if not the first pass\r
636 //\r
637 if (!FirstPass) {\r
638 //\r
639 // sequence version of for loop...\r
640 //\r
641 Info->Current += Info->Step;\r
642 }\r
643\r
644 TempString = AllocateZeroPool(50*sizeof(CHAR16));\r
645 UnicodeSPrint(TempString, 50*sizeof(CHAR16), L"%d", Info->Current);\r
646 InternalUpdateAliasOnList(Info->ReplacementName, TempString, &CurrentScriptFile->SubstList);\r
647 FreePool(TempString);\r
648\r
649 if ((Info->Step > 0 && Info->Current > Info->End) || (Info->Step < 0 && Info->Current < Info->End)) {\r
650 CurrentScriptFile->CurrentCommand->Data = NULL;\r
651 //\r
652 // find the matching endfor (we're done with the loop)\r
653 //\r
654 if (!MoveToTag(GetNextNode, L"endfor", L"for", NULL, CurrentScriptFile, TRUE, FALSE, FALSE)) {\r
ae724571 655 ShellPrintHiiEx(\r
ba0014b9
LG
656 -1,\r
657 -1,\r
658 NULL,\r
659 STRING_TOKEN (STR_SYNTAX_NO_MATCHING),\r
660 gShellLevel1HiiHandle,\r
661 L"EndFor",\r
662 L"For",\r
663 CurrentScriptFile!=NULL\r
ae724571 664 && CurrentScriptFile->CurrentCommand!=NULL\r
665 ? CurrentScriptFile->CurrentCommand->Line:0);\r
a405b86d 666 ShellStatus = SHELL_DEVICE_ERROR;\r
667 }\r
668 if (Info->RemoveSubstAlias) {\r
669 //\r
670 // remove item from list\r
671 //\r
672 InternalRemoveAliasFromList(Info->ReplacementName, &CurrentScriptFile->SubstList);\r
673 }\r
674 FreePool(Info);\r
675 }\r
676 } else {\r
677 //\r
678 // Must be in 'in' version of for loop...\r
679 //\r
680 ASSERT(Info->Set != NULL);\r
681 if (Info->CurrentValue != NULL && *Info->CurrentValue != CHAR_NULL) {\r
b471606b 682 if (Info->CurrentValue[0] == L' ') {\r
a405b86d 683 Info->CurrentValue++;\r
684 }\r
a405b86d 685 if (Info->CurrentValue[0] == L'\"') {\r
686 Info->CurrentValue++;\r
687 }\r
688 //\r
689 // do the next one of the set\r
690 //\r
691 ASSERT(TempString == NULL);\r
692 TempString = StrnCatGrow(&TempString, NULL, Info->CurrentValue, 0);\r
532691c8 693 if (TempString == NULL) {\r
694 ShellStatus = SHELL_OUT_OF_RESOURCES;\r
695 } else {\r
696 TempSpot = StrStr(TempString, L"\" \"");\r
697 if (TempSpot != NULL) {\r
698 *TempSpot = CHAR_NULL;\r
699 }\r
700 while (TempString[StrLen(TempString)-1] == L'\"') {\r
701 TempString[StrLen(TempString)-1] = CHAR_NULL;\r
702 }\r
703 InternalUpdateAliasOnList(Info->ReplacementName, TempString, &CurrentScriptFile->SubstList);\r
704 Info->CurrentValue += StrLen(TempString);\r
a405b86d 705\r
532691c8 706 if (Info->CurrentValue[0] == L'\"') {\r
707 Info->CurrentValue++;\r
708 }\r
709 FreePool(TempString);\r
a405b86d 710 }\r
a405b86d 711 } else {\r
712 CurrentScriptFile->CurrentCommand->Data = NULL;\r
713 //\r
714 // find the matching endfor (we're done with the loop)\r
715 //\r
716 if (!MoveToTag(GetNextNode, L"endfor", L"for", NULL, CurrentScriptFile, TRUE, FALSE, FALSE)) {\r
ae724571 717 ShellPrintHiiEx(\r
ba0014b9
LG
718 -1,\r
719 -1,\r
720 NULL,\r
721 STRING_TOKEN (STR_SYNTAX_NO_MATCHING),\r
722 gShellLevel1HiiHandle,\r
723 L"EndFor",\r
724 L"For",\r
725 CurrentScriptFile!=NULL\r
ae724571 726 && CurrentScriptFile->CurrentCommand!=NULL\r
727 ? CurrentScriptFile->CurrentCommand->Line:0);\r
a405b86d 728 ShellStatus = SHELL_DEVICE_ERROR;\r
729 }\r
730 if (Info->RemoveSubstAlias) {\r
731 //\r
732 // remove item from list\r
733 //\r
734 InternalRemoveAliasFromList(Info->ReplacementName, &CurrentScriptFile->SubstList);\r
735 }\r
736 FreePool(Info);\r
737 }\r
738 }\r
739 }\r
740 if (ArgSet != NULL) {\r
741 FreePool(ArgSet);\r
742 }\r
743 return (ShellStatus);\r
744}\r
745\r