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