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