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