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