]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellLevel1CommandsLib/For.c
Updating level 1 commands.
[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
77dcec12 4 Copyright (c) 2009 - 2011, 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
45 if (StrStr(Number, L" ") != NULL && (StrStr(Number, L" ") - Number) >= 7) {\r
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
72\r
73 Status = CommandInit();\r
74 ASSERT_EFI_ERROR(Status);\r
75\r
76 if (!gEfiShellProtocol->BatchIsActive()) {\r
77 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"EndFor");\r
78 return (SHELL_UNSUPPORTED);\r
79 }\r
80\r
81 if (gEfiShellParametersProtocol->Argc > 1) {\r
82 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle);\r
83 return (SHELL_INVALID_PARAMETER);\r
84 }\r
85\r
86 Found = MoveToTag(GetPreviousNode, L"for", L"endfor", NULL, ShellCommandGetCurrentScriptFile(), FALSE, FALSE, FALSE);\r
87\r
88 if (!Found) {\r
89 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"For", L"EndFor", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);\r
90 return (SHELL_NOT_FOUND);\r
91 }\r
92 return (SHELL_SUCCESS);\r
93}\r
94\r
95typedef struct {\r
96 UINT32 Signature;\r
97 INTN Current;\r
98 INTN End;\r
99 INTN Step;\r
100 CHAR16 *ReplacementName;\r
101 CHAR16 *CurrentValue;\r
102 BOOLEAN RemoveSubstAlias;\r
103 CHAR16 Set[1];\r
104 } SHELL_FOR_INFO;\r
105#define SIZE_OF_SHELL_FOR_INFO OFFSET_OF (SHELL_FOR_INFO, Set)\r
106#define SHELL_FOR_INFO_SIGNATURE SIGNATURE_32 ('S', 'F', 'I', 's')\r
107\r
108/**\r
109 Update the value of a given alias on the list. If the alias is not there then add it.\r
110\r
111 @param[in] Alias The alias to test for.\r
112 @param[in] CommandString The updated command string.\r
113 @param[in,out] List The list to search.\r
9ea69f8a 114\r
115 @retval EFI_SUCCESS The operation was completed successfully.\r
116 @retval EFI_OUT_OF_RESOURCES There was not enough free memory.\r
a405b86d 117**/\r
9ea69f8a 118EFI_STATUS\r
a405b86d 119EFIAPI\r
120InternalUpdateAliasOnList(\r
121 IN CONST CHAR16 *Alias,\r
122 IN CONST CHAR16 *CommandString,\r
123 IN OUT LIST_ENTRY *List\r
124 )\r
125{\r
126 ALIAS_LIST *Node;\r
127 BOOLEAN Found;\r
128\r
129 //\r
130 // assert for NULL parameter\r
131 //\r
132 ASSERT(Alias != NULL);\r
133\r
134 //\r
135 // check for the Alias\r
136 //\r
137 for ( Node = (ALIAS_LIST *)GetFirstNode(List), Found = FALSE\r
138 ; !IsNull(List, &Node->Link)\r
139 ; Node = (ALIAS_LIST *)GetNextNode(List, &Node->Link)\r
140 ){\r
141 ASSERT(Node->CommandString != NULL);\r
142 ASSERT(Node->Alias != NULL);\r
143 if (StrCmp(Node->Alias, Alias)==0) {\r
144 FreePool(Node->CommandString);\r
145 Node->CommandString = NULL;\r
146 Node->CommandString = StrnCatGrow(&Node->CommandString, NULL, CommandString, 0);\r
147 Found = TRUE;\r
148 break;\r
149 }\r
150 }\r
151 if (!Found) {\r
152 Node = AllocateZeroPool(sizeof(ALIAS_LIST));\r
9ea69f8a 153 if (Node == NULL) {\r
154 return (EFI_OUT_OF_RESOURCES);\r
155 }\r
a405b86d 156 ASSERT(Node->Alias == NULL);\r
157 Node->Alias = StrnCatGrow(&Node->Alias, NULL, Alias, 0);\r
158 ASSERT(Node->CommandString == NULL);\r
159 Node->CommandString = StrnCatGrow(&Node->CommandString, NULL, CommandString, 0);\r
160 InsertTailList(List, &Node->Link);\r
161 }\r
9ea69f8a 162 return (EFI_SUCCESS);\r
a405b86d 163}\r
164\r
165/**\r
166 Find out if an alias is on the given list.\r
167\r
168 @param[in] Alias The alias to test for.\r
169 @param[in] List The list to search.\r
170\r
171 @retval TRUE The alias is on the list.\r
172 @retval FALSE The alias is not on the list.\r
173**/\r
174BOOLEAN\r
175EFIAPI\r
176InternalIsAliasOnList(\r
177 IN CONST CHAR16 *Alias,\r
178 IN CONST LIST_ENTRY *List\r
179 )\r
180{\r
181 ALIAS_LIST *Node;\r
182\r
183 //\r
184 // assert for NULL parameter\r
185 //\r
186 ASSERT(Alias != NULL);\r
187\r
188 //\r
189 // check for the Alias\r
190 //\r
191 for ( Node = (ALIAS_LIST *)GetFirstNode(List)\r
192 ; !IsNull(List, &Node->Link)\r
193 ; Node = (ALIAS_LIST *)GetNextNode(List, &Node->Link)\r
194 ){\r
195 ASSERT(Node->CommandString != NULL);\r
196 ASSERT(Node->Alias != NULL);\r
197 if (StrCmp(Node->Alias, Alias)==0) {\r
198 return (TRUE);\r
199 }\r
200 }\r
201 return (FALSE);\r
202}\r
203\r
204/**\r
205 Remove an alias from the given list.\r
206\r
207 @param[in] Alias The alias to remove.\r
208 @param[in,out] List The list to search.\r
209**/\r
210BOOLEAN\r
211EFIAPI\r
212InternalRemoveAliasFromList(\r
213 IN CONST CHAR16 *Alias,\r
214 IN OUT LIST_ENTRY *List\r
215 )\r
216{\r
217 ALIAS_LIST *Node;\r
218\r
219 //\r
220 // assert for NULL parameter\r
221 //\r
222 ASSERT(Alias != NULL);\r
223\r
224 //\r
225 // check for the Alias\r
226 //\r
227 for ( Node = (ALIAS_LIST *)GetFirstNode(List)\r
228 ; !IsNull(List, &Node->Link)\r
229 ; Node = (ALIAS_LIST *)GetNextNode(List, &Node->Link)\r
230 ){\r
231 ASSERT(Node->CommandString != NULL);\r
232 ASSERT(Node->Alias != NULL);\r
233 if (StrCmp(Node->Alias, Alias)==0) {\r
234 RemoveEntryList(&Node->Link);\r
235 FreePool(Node->Alias);\r
236 FreePool(Node->CommandString);\r
237 FreePool(Node);\r
238 return (TRUE);\r
239 }\r
240 }\r
241 return (FALSE);\r
242}\r
243\r
244/**\r
245 Function for 'for' command.\r
246\r
247 @param[in] ImageHandle Handle to the Image (NULL if Internal).\r
248 @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r
249**/\r
250SHELL_STATUS\r
251EFIAPI\r
252ShellCommandRunFor (\r
253 IN EFI_HANDLE ImageHandle,\r
254 IN EFI_SYSTEM_TABLE *SystemTable\r
255 )\r
256{\r
257 EFI_STATUS Status;\r
258 SHELL_STATUS ShellStatus;\r
259 SCRIPT_FILE *CurrentScriptFile;\r
260 CHAR16 *ArgSet;\r
261 CHAR16 *ArgSetWalker;\r
262 UINTN ArgSize;\r
263 UINTN LoopVar;\r
264 SHELL_FOR_INFO *Info;\r
265 CHAR16 *TempString;\r
266 CHAR16 *TempSpot;\r
267 BOOLEAN FirstPass;\r
268 EFI_SHELL_FILE_INFO *Node;\r
269 EFI_SHELL_FILE_INFO *FileList;\r
270 UINTN NewSize;\r
271\r
272 ArgSet = NULL;\r
273 ArgSize = 0;\r
274 ShellStatus = SHELL_SUCCESS;\r
275 ArgSetWalker = NULL;\r
276 TempString = NULL;\r
277 FirstPass = FALSE;\r
278\r
279 //\r
280 // initialize the shell lib (we must be in non-auto-init...)\r
281 //\r
282 Status = ShellInitialize();\r
283 ASSERT_EFI_ERROR(Status);\r
284\r
285 Status = CommandInit();\r
286 ASSERT_EFI_ERROR(Status);\r
287\r
288 if (!gEfiShellProtocol->BatchIsActive()) {\r
289 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"For");\r
290 return (SHELL_UNSUPPORTED);\r
291 }\r
292\r
293 if (gEfiShellParametersProtocol->Argc < 4) {\r
294 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel1HiiHandle);\r
295 return (SHELL_INVALID_PARAMETER);\r
296 }\r
297\r
298 CurrentScriptFile = ShellCommandGetCurrentScriptFile();\r
299 ASSERT(CurrentScriptFile != NULL);\r
300\r
301 if (CurrentScriptFile->CurrentCommand->Data == NULL) {\r
302 FirstPass = TRUE;\r
303\r
304 //\r
305 // Make sure that an End exists.\r
306 //\r
307 if (!MoveToTag(GetNextNode, L"endfor", L"for", NULL, CurrentScriptFile, TRUE, TRUE, FALSE)) {\r
308 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"EndFor", L"For", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);\r
309 return (SHELL_DEVICE_ERROR);\r
310 }\r
311\r
312 //\r
313 // Process the line.\r
314 //\r
315 if (gEfiShellParametersProtocol->Argv[1][0] != L'%' || gEfiShellParametersProtocol->Argv[1][2] != CHAR_NULL\r
316 ||!((gEfiShellParametersProtocol->Argv[1][1] >= L'a' && gEfiShellParametersProtocol->Argv[1][1] <= L'z')\r
317 ||(gEfiShellParametersProtocol->Argv[1][1] >= L'A' && gEfiShellParametersProtocol->Argv[1][1] <= L'Z'))\r
318 ) {\r
77dcec12 319 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_VAR), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[1]);\r
a405b86d 320 return (SHELL_INVALID_PARAMETER);\r
321 }\r
322\r
323 if (gUnicodeCollation->StriColl(\r
324 gUnicodeCollation,\r
325 L"in",\r
326 gEfiShellParametersProtocol->Argv[2]) == 0) {\r
327 for (LoopVar = 0x3 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) {\r
328 ASSERT((ArgSet == NULL && ArgSize == 0) || (ArgSet != NULL));\r
329 if (ArgSet == NULL) {\r
330 // ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0);\r
331 } else {\r
332 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" \"", 0);\r
333 }\r
334 if (StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"*") != NULL\r
335 ||StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"?") != NULL\r
336 ||StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"[") != NULL\r
337 ||StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"]") != NULL) {\r
338 FileList = NULL;\r
339 Status = ShellOpenFileMetaArg ((CHAR16*)gEfiShellParametersProtocol->Argv[LoopVar], EFI_FILE_MODE_READ, &FileList);\r
340 if (EFI_ERROR(Status) || FileList == NULL || IsListEmpty(&FileList->Link)) {\r
341 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, gEfiShellParametersProtocol->Argv[LoopVar], 0);\r
342 } else {\r
343 for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link)\r
344 ; !IsNull(&FileList->Link, &Node->Link)\r
345 ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link)\r
346 ){\r
347 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" \"", 0);\r
348 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, Node->FullName, 0);\r
349 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0);\r
350 }\r
351 ShellCloseFileMetaArg(&FileList);\r
352 }\r
353 } else {\r
354 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, gEfiShellParametersProtocol->Argv[LoopVar], 0);\r
355 }\r
356 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0);\r
357 }\r
358 //\r
359 // set up for an 'in' for loop\r
360 //\r
361 NewSize = StrSize(ArgSet);\r
362 NewSize += sizeof(SHELL_FOR_INFO)+StrSize(gEfiShellParametersProtocol->Argv[1]);\r
363 Info = AllocateZeroPool(NewSize);\r
364 ASSERT(Info != NULL);\r
365 Info->Signature = SHELL_FOR_INFO_SIGNATURE;\r
366 CopyMem(Info->Set, ArgSet, StrSize(ArgSet));\r
367 NewSize = StrSize(gEfiShellParametersProtocol->Argv[1]);\r
368 CopyMem(Info->Set+(StrSize(ArgSet)/sizeof(Info->Set[0])), gEfiShellParametersProtocol->Argv[1], NewSize);\r
369 Info->ReplacementName = Info->Set+StrSize(ArgSet)/sizeof(Info->Set[0]);\r
370 Info->CurrentValue = (CHAR16*)Info->Set;\r
371 Info->Step = 0;\r
372 Info->Current = 0;\r
373 Info->End = 0;\r
374\r
375 if (InternalIsAliasOnList(Info->ReplacementName, &CurrentScriptFile->SubstList)) {\r
376 Info->RemoveSubstAlias = FALSE;\r
377 } else {\r
378 Info->RemoveSubstAlias = TRUE;\r
379 }\r
380 CurrentScriptFile->CurrentCommand->Data = Info;\r
381 } else if (gUnicodeCollation->StriColl(\r
382 gUnicodeCollation,\r
383 L"run",\r
384 gEfiShellParametersProtocol->Argv[2]) == 0) {\r
385 for (LoopVar = 0x3 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) {\r
386 ASSERT((ArgSet == NULL && ArgSize == 0) || (ArgSet != NULL));\r
387 if (ArgSet == NULL) {\r
388// ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0);\r
389 } else {\r
77dcec12 390 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" ", 0);\r
a405b86d 391 }\r
392 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, gEfiShellParametersProtocol->Argv[LoopVar], 0);\r
393// ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" ", 0);\r
394 }\r
395 //\r
396 // set up for a 'run' for loop\r
397 //\r
398 Info = AllocateZeroPool(sizeof(SHELL_FOR_INFO)+StrSize(gEfiShellParametersProtocol->Argv[1]));\r
399 ASSERT(Info != NULL);\r
400 CopyMem(Info->Set, gEfiShellParametersProtocol->Argv[1], StrSize(gEfiShellParametersProtocol->Argv[1]));\r
401 Info->ReplacementName = Info->Set;\r
402 Info->CurrentValue = NULL;\r
403 ArgSetWalker = ArgSet;\r
404 if (ArgSetWalker[0] != L'(') {\r
405 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), gShellLevel1HiiHandle, ArgSet, ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);\r
406 ShellStatus = SHELL_INVALID_PARAMETER;\r
407 } else {\r
77dcec12 408 TempSpot = StrStr(ArgSetWalker, L")");\r
409 if (TempSpot != NULL) {\r
410 TempString = TempSpot+1;\r
411 if (*(TempString) != CHAR_NULL) {\r
412 while(TempString != NULL && *TempString == L' ') {\r
413 TempString++;\r
414 }\r
415 if (StrLen(TempString) > 0) {\r
416 TempSpot = NULL;\r
417 }\r
418 }\r
a405b86d 419 }\r
77dcec12 420 if (TempSpot == NULL) {\r
a405b86d 421 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), gShellLevel1HiiHandle, ArgSet, ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);\r
422 ShellStatus = SHELL_INVALID_PARAMETER;\r
423 } else {\r
77dcec12 424 *TempSpot = CHAR_NULL;\r
425 ArgSetWalker++;\r
a405b86d 426 while (ArgSetWalker != NULL && ArgSetWalker[0] == L' ') {\r
427 ArgSetWalker++;\r
428 }\r
77dcec12 429 if (!ShellIsValidForNumber(ArgSetWalker)) {\r
a405b86d 430 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), gShellLevel1HiiHandle, ArgSet, ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);\r
431 ShellStatus = SHELL_INVALID_PARAMETER;\r
432 } else {\r
433 if (ArgSetWalker[0] == L'-') {\r
77dcec12 434 Info->Current = 0 - (INTN)ShellStrToUintn(ArgSetWalker+1);\r
a405b86d 435 } else {\r
77dcec12 436 Info->Current = (INTN)ShellStrToUintn(ArgSetWalker);\r
a405b86d 437 }\r
a405b86d 438 ArgSetWalker = StrStr(ArgSetWalker, L" ");\r
439 while (ArgSetWalker != NULL && ArgSetWalker[0] == L' ') {\r
440 ArgSetWalker++;\r
441 }\r
77dcec12 442 if (ArgSetWalker == NULL || *ArgSetWalker == CHAR_NULL || !ShellIsValidForNumber(ArgSetWalker)){\r
443 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), gShellLevel1HiiHandle, ArgSet, ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);\r
444 ShellStatus = SHELL_INVALID_PARAMETER;\r
445 } else {\r
446 if (ArgSetWalker[0] == L'-') {\r
447 Info->End = 0 - (INTN)ShellStrToUintn(ArgSetWalker+1);\r
a405b86d 448 } else {\r
77dcec12 449 Info->End = (INTN)ShellStrToUintn(ArgSetWalker);\r
450 }\r
451 if (Info->Current < Info->End) {\r
452 Info->Step = 1;\r
453 } else {\r
454 Info->Step = -1;\r
455 }\r
456\r
457 ArgSetWalker = StrStr(ArgSetWalker, L" ");\r
458 while (ArgSetWalker != NULL && ArgSetWalker[0] == L' ') {\r
459 ArgSetWalker++;\r
460 }\r
461 if (ArgSetWalker != NULL && *ArgSetWalker != CHAR_NULL) {\r
a405b86d 462 if (ArgSetWalker == NULL || *ArgSetWalker == CHAR_NULL || !ShellIsValidForNumber(ArgSetWalker)){\r
463 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), gShellLevel1HiiHandle, ArgSet, ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);\r
464 ShellStatus = SHELL_INVALID_PARAMETER;\r
465 } else {\r
466 if (*ArgSetWalker == L')') {\r
467 ASSERT(Info->Step == 1 || Info->Step == -1);\r
468 } else {\r
469 if (ArgSetWalker[0] == L'-') {\r
470 Info->Step = 0 - (INTN)ShellStrToUintn(ArgSetWalker+1);\r
471 } else {\r
472 Info->Step = (INTN)ShellStrToUintn(ArgSetWalker);\r
473 }\r
77dcec12 474\r
475 if (StrStr(ArgSetWalker, L" ") != NULL) {\r
476 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), gShellLevel1HiiHandle, ArgSet, ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);\r
477 ShellStatus = SHELL_INVALID_PARAMETER;\r
478 }\r
a405b86d 479 }\r
480 }\r
77dcec12 481 \r
a405b86d 482 }\r
483 }\r
484 }\r
485 }\r
486 }\r
487 if (ShellStatus == SHELL_SUCCESS) {\r
488 if (InternalIsAliasOnList(Info->ReplacementName, &CurrentScriptFile->SubstList)) {\r
489 Info->RemoveSubstAlias = FALSE;\r
490 } else {\r
491 Info->RemoveSubstAlias = TRUE;\r
492 }\r
493 }\r
494 CurrentScriptFile->CurrentCommand->Data = Info;\r
495 } else {\r
496 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), gShellLevel1HiiHandle, ArgSet, ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);\r
497 ShellStatus = SHELL_INVALID_PARAMETER;\r
498 }\r
499 } else {\r
500 //\r
501 // These need to be NULL since they are used to determine if this is the first pass later on...\r
502 //\r
503 ASSERT(ArgSetWalker == NULL);\r
504 ASSERT(ArgSet == NULL);\r
505 }\r
506\r
507 Info = (SHELL_FOR_INFO*)CurrentScriptFile->CurrentCommand->Data;\r
508 if (CurrentScriptFile->CurrentCommand->Reset) {\r
509 Info->CurrentValue = (CHAR16*)Info->Set;\r
510 FirstPass = TRUE;\r
511 CurrentScriptFile->CurrentCommand->Reset = FALSE;\r
512 }\r
513 if (ShellStatus == SHELL_SUCCESS) {\r
514 ASSERT(Info != NULL);\r
515 if (Info->Step != 0) {\r
516 //\r
517 // only advance if not the first pass\r
518 //\r
519 if (!FirstPass) {\r
520 //\r
521 // sequence version of for loop...\r
522 //\r
523 Info->Current += Info->Step;\r
524 }\r
525\r
526 TempString = AllocateZeroPool(50*sizeof(CHAR16));\r
527 UnicodeSPrint(TempString, 50*sizeof(CHAR16), L"%d", Info->Current);\r
528 InternalUpdateAliasOnList(Info->ReplacementName, TempString, &CurrentScriptFile->SubstList);\r
529 FreePool(TempString);\r
530\r
531 if ((Info->Step > 0 && Info->Current > Info->End) || (Info->Step < 0 && Info->Current < Info->End)) {\r
532 CurrentScriptFile->CurrentCommand->Data = NULL;\r
533 //\r
534 // find the matching endfor (we're done with the loop)\r
535 //\r
536 if (!MoveToTag(GetNextNode, L"endfor", L"for", NULL, CurrentScriptFile, TRUE, FALSE, FALSE)) {\r
537 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"EndFor", L"For", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);\r
538 ShellStatus = SHELL_DEVICE_ERROR;\r
539 }\r
540 if (Info->RemoveSubstAlias) {\r
541 //\r
542 // remove item from list\r
543 //\r
544 InternalRemoveAliasFromList(Info->ReplacementName, &CurrentScriptFile->SubstList);\r
545 }\r
546 FreePool(Info);\r
547 }\r
548 } else {\r
549 //\r
550 // Must be in 'in' version of for loop...\r
551 //\r
552 ASSERT(Info->Set != NULL);\r
553 if (Info->CurrentValue != NULL && *Info->CurrentValue != CHAR_NULL) {\r
554 if (Info->CurrentValue[0] == L'\"') {\r
555 Info->CurrentValue++;\r
556 }\r
77dcec12 557// while (Info->CurrentValue[0] == L' ') {\r
558// Info->CurrentValue++;\r
559// }\r
a405b86d 560 if (Info->CurrentValue[0] == L'\"') {\r
561 Info->CurrentValue++;\r
562 }\r
563 //\r
564 // do the next one of the set\r
565 //\r
566 ASSERT(TempString == NULL);\r
567 TempString = StrnCatGrow(&TempString, NULL, Info->CurrentValue, 0);\r
568 TempSpot = StrStr(TempString, L"\" \"");\r
569 if (TempSpot != NULL) {\r
570 *TempSpot = CHAR_NULL;\r
571 }\r
572 while (TempString[StrLen(TempString)-1] == L'\"') {\r
573 TempString[StrLen(TempString)-1] = CHAR_NULL;\r
574 }\r
575 InternalUpdateAliasOnList(Info->ReplacementName, TempString, &CurrentScriptFile->SubstList);\r
576 Info->CurrentValue += StrLen(TempString);\r
577\r
578 if (Info->CurrentValue[0] == L'\"') {\r
579 Info->CurrentValue++;\r
580 }\r
581 while (Info->CurrentValue[0] == L' ') {\r
582 Info->CurrentValue++;\r
583 }\r
584 if (Info->CurrentValue[0] == L'\"') {\r
585 Info->CurrentValue++;\r
586 }\r
587 FreePool(TempString);\r
588\r
589 } else {\r
590 CurrentScriptFile->CurrentCommand->Data = NULL;\r
591 //\r
592 // find the matching endfor (we're done with the loop)\r
593 //\r
594 if (!MoveToTag(GetNextNode, L"endfor", L"for", NULL, CurrentScriptFile, TRUE, FALSE, FALSE)) {\r
595 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_NO_MATCHING), gShellLevel1HiiHandle, L"EndFor", L"For", ShellCommandGetCurrentScriptFile()->CurrentCommand->Line);\r
596 ShellStatus = SHELL_DEVICE_ERROR;\r
597 }\r
598 if (Info->RemoveSubstAlias) {\r
599 //\r
600 // remove item from list\r
601 //\r
602 InternalRemoveAliasFromList(Info->ReplacementName, &CurrentScriptFile->SubstList);\r
603 }\r
604 FreePool(Info);\r
605 }\r
606 }\r
607 }\r
608 if (ArgSet != NULL) {\r
609 FreePool(ArgSet);\r
610 }\r
611 return (ShellStatus);\r
612}\r
613\r