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