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