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