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 - 2014, Intel Corporation. All rights reserved.<BR> 6 This program and the accompanying materials 7 are licensed and made available under the terms and conditions of the BSD License 8 which accompanies this distribution. The full text of the license may be found at 9 http://opensource.org/licenses/bsd-license.php 10 11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 13 14 **/ 15 16 #include "UefiShellLevel1CommandsLib.h" 17 #include <Library/PrintLib.h> 18 19 /** 20 Determine if a valid string is a valid number for the 'for' command. 21 22 @param[in] Number The pointer to the string representation of the number to test. 23 24 @retval TRUE The number is valid. 25 @retval FALSE The number is not valid. 26 **/ 27 BOOLEAN 28 EFIAPI 29 ShellIsValidForNumber ( 30 IN CONST CHAR16 *Number 31 ) 32 { 33 if (Number == NULL || *Number == CHAR_NULL) { 34 return (FALSE); 35 } 36 37 if (*Number == L'-') { 38 Number++; 39 } 40 41 if (StrLen(Number) == 0) { 42 return (FALSE); 43 } 44 45 if (StrLen(Number) >= 7) { 46 if ((StrStr(Number, L" ") == NULL) || (((StrStr(Number, L" ") != NULL) && (StrStr(Number, L" ") - Number) >= 7))) { 47 return (FALSE); 48 } 49 } 50 51 if (!ShellIsDecimalDigitCharacter(*Number)) { 52 return (FALSE); 53 } 54 55 return (TRUE); 56 } 57 58 /** 59 Function for 'endfor' command. 60 61 @param[in] ImageHandle Handle to the Image (NULL if Internal). 62 @param[in] SystemTable Pointer to the System Table (NULL if Internal). 63 **/ 64 SHELL_STATUS 65 EFIAPI 66 ShellCommandRunEndFor ( 67 IN EFI_HANDLE ImageHandle, 68 IN EFI_SYSTEM_TABLE *SystemTable 69 ) 70 { 71 EFI_STATUS Status; 72 BOOLEAN Found; 73 SCRIPT_FILE *CurrentScriptFile; 74 75 Status = CommandInit(); 76 ASSERT_EFI_ERROR(Status); 77 78 if (!gEfiShellProtocol->BatchIsActive()) { 79 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"endfor"); 80 return (SHELL_UNSUPPORTED); 81 } 82 83 if (gEfiShellParametersProtocol->Argc > 1) { 84 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle, L"endfor"); 85 return (SHELL_INVALID_PARAMETER); 86 } 87 88 Found = MoveToTag(GetPreviousNode, L"for", L"endfor", NULL, ShellCommandGetCurrentScriptFile(), FALSE, FALSE, FALSE); 89 90 if (!Found) { 91 CurrentScriptFile = ShellCommandGetCurrentScriptFile(); 92 ShellPrintHiiEx( 93 -1, 94 -1, 95 NULL, 96 STRING_TOKEN (STR_SYNTAX_NO_MATCHING), 97 gShellLevel1HiiHandle, 98 L"For", 99 L"EndFor", 100 CurrentScriptFile!=NULL 101 && CurrentScriptFile->CurrentCommand!=NULL 102 ? CurrentScriptFile->CurrentCommand->Line:0); 103 return (SHELL_NOT_FOUND); 104 } 105 return (SHELL_SUCCESS); 106 } 107 108 typedef struct { 109 UINT32 Signature; 110 INTN Current; 111 INTN End; 112 INTN Step; 113 CHAR16 *ReplacementName; 114 CHAR16 *CurrentValue; 115 BOOLEAN RemoveSubstAlias; 116 CHAR16 Set[1]; 117 } SHELL_FOR_INFO; 118 #define SIZE_OF_SHELL_FOR_INFO OFFSET_OF (SHELL_FOR_INFO, Set) 119 #define SHELL_FOR_INFO_SIGNATURE SIGNATURE_32 ('S', 'F', 'I', 's') 120 121 /** 122 Update the value of a given alias on the list. If the alias is not there then add it. 123 124 @param[in] Alias The alias to test for. 125 @param[in] CommandString The updated command string. 126 @param[in, out] List The list to search. 127 128 @retval EFI_SUCCESS The operation was completed successfully. 129 @retval EFI_OUT_OF_RESOURCES There was not enough free memory. 130 **/ 131 EFI_STATUS 132 EFIAPI 133 InternalUpdateAliasOnList( 134 IN CONST CHAR16 *Alias, 135 IN CONST CHAR16 *CommandString, 136 IN OUT LIST_ENTRY *List 137 ) 138 { 139 ALIAS_LIST *Node; 140 BOOLEAN Found; 141 142 // 143 // assert for NULL parameter 144 // 145 ASSERT(Alias != NULL); 146 147 // 148 // check for the Alias 149 // 150 for ( Node = (ALIAS_LIST *)GetFirstNode(List), Found = FALSE 151 ; !IsNull(List, &Node->Link) 152 ; Node = (ALIAS_LIST *)GetNextNode(List, &Node->Link) 153 ){ 154 ASSERT(Node->CommandString != NULL); 155 ASSERT(Node->Alias != NULL); 156 if (StrCmp(Node->Alias, Alias)==0) { 157 FreePool(Node->CommandString); 158 Node->CommandString = NULL; 159 Node->CommandString = StrnCatGrow(&Node->CommandString, NULL, CommandString, 0); 160 Found = TRUE; 161 break; 162 } 163 } 164 if (!Found) { 165 Node = AllocateZeroPool(sizeof(ALIAS_LIST)); 166 if (Node == NULL) { 167 return (EFI_OUT_OF_RESOURCES); 168 } 169 ASSERT(Node->Alias == NULL); 170 Node->Alias = StrnCatGrow(&Node->Alias, NULL, Alias, 0); 171 ASSERT(Node->CommandString == NULL); 172 Node->CommandString = StrnCatGrow(&Node->CommandString, NULL, CommandString, 0); 173 InsertTailList(List, &Node->Link); 174 } 175 return (EFI_SUCCESS); 176 } 177 178 /** 179 Find out if an alias is on the given list. 180 181 @param[in] Alias The alias to test for. 182 @param[in] List The list to search. 183 184 @retval TRUE The alias is on the list. 185 @retval FALSE The alias is not on the list. 186 **/ 187 BOOLEAN 188 EFIAPI 189 InternalIsAliasOnList( 190 IN CONST CHAR16 *Alias, 191 IN CONST LIST_ENTRY *List 192 ) 193 { 194 ALIAS_LIST *Node; 195 196 // 197 // assert for NULL parameter 198 // 199 ASSERT(Alias != NULL); 200 201 // 202 // check for the Alias 203 // 204 for ( Node = (ALIAS_LIST *)GetFirstNode(List) 205 ; !IsNull(List, &Node->Link) 206 ; Node = (ALIAS_LIST *)GetNextNode(List, &Node->Link) 207 ){ 208 ASSERT(Node->CommandString != NULL); 209 ASSERT(Node->Alias != NULL); 210 if (StrCmp(Node->Alias, Alias)==0) { 211 return (TRUE); 212 } 213 } 214 return (FALSE); 215 } 216 217 /** 218 Remove an alias from the given list. 219 220 @param[in] Alias The alias to remove. 221 @param[in, out] List The list to search. 222 **/ 223 BOOLEAN 224 EFIAPI 225 InternalRemoveAliasFromList( 226 IN CONST CHAR16 *Alias, 227 IN OUT LIST_ENTRY *List 228 ) 229 { 230 ALIAS_LIST *Node; 231 232 // 233 // assert for NULL parameter 234 // 235 ASSERT(Alias != NULL); 236 237 // 238 // check for the Alias 239 // 240 for ( Node = (ALIAS_LIST *)GetFirstNode(List) 241 ; !IsNull(List, &Node->Link) 242 ; Node = (ALIAS_LIST *)GetNextNode(List, &Node->Link) 243 ){ 244 ASSERT(Node->CommandString != NULL); 245 ASSERT(Node->Alias != NULL); 246 if (StrCmp(Node->Alias, Alias)==0) { 247 RemoveEntryList(&Node->Link); 248 FreePool(Node->Alias); 249 FreePool(Node->CommandString); 250 FreePool(Node); 251 return (TRUE); 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 EFIAPI 268 ReturnUintn( 269 IN CONST CHAR16 *String 270 ) 271 { 272 UINT64 RetVal; 273 274 if (!EFI_ERROR(ShellConvertStringToUint64(String, &RetVal, FALSE, TRUE))) { 275 return ((UINTN)RetVal); 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 return (SHELL_DEVICE_ERROR); 356 } 357 358 // 359 // Process the line. 360 // 361 if (gEfiShellParametersProtocol->Argv[1][0] != L'%' || gEfiShellParametersProtocol->Argv[1][2] != CHAR_NULL 362 ||!((gEfiShellParametersProtocol->Argv[1][1] >= L'a' && gEfiShellParametersProtocol->Argv[1][1] <= L'z') 363 ||(gEfiShellParametersProtocol->Argv[1][1] >= L'A' && gEfiShellParametersProtocol->Argv[1][1] <= L'Z')) 364 ) { 365 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_VAR), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[1]); 366 return (SHELL_INVALID_PARAMETER); 367 } 368 369 if (gUnicodeCollation->StriColl( 370 gUnicodeCollation, 371 L"in", 372 gEfiShellParametersProtocol->Argv[2]) == 0) { 373 for (LoopVar = 0x3 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) { 374 ASSERT((ArgSet == NULL && ArgSize == 0) || (ArgSet != NULL)); 375 if (StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"*") != NULL 376 ||StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"?") != NULL 377 ||StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"[") != NULL 378 ||StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"]") != NULL) { 379 FileList = NULL; 380 Status = ShellOpenFileMetaArg ((CHAR16*)gEfiShellParametersProtocol->Argv[LoopVar], EFI_FILE_MODE_READ, &FileList); 381 if (EFI_ERROR(Status) || FileList == NULL || IsListEmpty(&FileList->Link)) { 382 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" \"", 0); 383 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, gEfiShellParametersProtocol->Argv[LoopVar], 0); 384 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0); 385 } else { 386 for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link) 387 ; !IsNull(&FileList->Link, &Node->Link) 388 ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link) 389 ){ 390 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" \"", 0); 391 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, Node->FullName, 0); 392 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0); 393 } 394 ShellCloseFileMetaArg(&FileList); 395 } 396 } else { 397 Parameter = gEfiShellParametersProtocol->Argv[LoopVar]; 398 if (Parameter[0] == L'\"' && Parameter[StrLen(Parameter)-1] == L'\"') { 399 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" ", 0); 400 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, Parameter, 0); 401 } else { 402 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" \"", 0); 403 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, Parameter, 0); 404 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0); 405 } 406 } 407 } 408 if (ArgSet == NULL) { 409 ShellStatus = SHELL_OUT_OF_RESOURCES; 410 } else { 411 // 412 // set up for an 'in' for loop 413 // 414 NewSize = StrSize(ArgSet); 415 NewSize += sizeof(SHELL_FOR_INFO)+StrSize(gEfiShellParametersProtocol->Argv[1]); 416 Info = AllocateZeroPool(NewSize); 417 ASSERT(Info != NULL); 418 Info->Signature = SHELL_FOR_INFO_SIGNATURE; 419 CopyMem(Info->Set, ArgSet, StrSize(ArgSet)); 420 NewSize = StrSize(gEfiShellParametersProtocol->Argv[1]); 421 CopyMem(Info->Set+(StrSize(ArgSet)/sizeof(Info->Set[0])), gEfiShellParametersProtocol->Argv[1], NewSize); 422 Info->ReplacementName = Info->Set+StrSize(ArgSet)/sizeof(Info->Set[0]); 423 Info->CurrentValue = (CHAR16*)Info->Set; 424 Info->Step = 0; 425 Info->Current = 0; 426 Info->End = 0; 427 428 if (InternalIsAliasOnList(Info->ReplacementName, &CurrentScriptFile->SubstList)) { 429 Info->RemoveSubstAlias = FALSE; 430 } else { 431 Info->RemoveSubstAlias = TRUE; 432 } 433 CurrentScriptFile->CurrentCommand->Data = Info; 434 } 435 } else if (gUnicodeCollation->StriColl( 436 gUnicodeCollation, 437 L"run", 438 gEfiShellParametersProtocol->Argv[2]) == 0) { 439 for (LoopVar = 0x3 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) { 440 ASSERT((ArgSet == NULL && ArgSize == 0) || (ArgSet != NULL)); 441 if (StrStr (gEfiShellParametersProtocol->Argv[LoopVar], L")") != NULL && 442 (LoopVar + 1) < gEfiShellParametersProtocol->Argc 443 ) { 444 return (SHELL_INVALID_PARAMETER); 445 } 446 if (ArgSet == NULL) { 447 // ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0); 448 } else { 449 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" ", 0); 450 } 451 ArgSet = StrnCatGrow(&ArgSet, &ArgSize, gEfiShellParametersProtocol->Argv[LoopVar], 0); 452 // ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" ", 0); 453 } 454 if (ArgSet == NULL) { 455 ShellStatus = SHELL_OUT_OF_RESOURCES; 456 } else { 457 // 458 // set up for a 'run' for loop 459 // 460 Info = AllocateZeroPool(sizeof(SHELL_FOR_INFO)+StrSize(gEfiShellParametersProtocol->Argv[1])); 461 ASSERT(Info != NULL); 462 Info->Signature = SHELL_FOR_INFO_SIGNATURE; 463 CopyMem(Info->Set, gEfiShellParametersProtocol->Argv[1], StrSize(gEfiShellParametersProtocol->Argv[1])); 464 Info->ReplacementName = Info->Set; 465 Info->CurrentValue = NULL; 466 ArgSetWalker = ArgSet; 467 if (ArgSetWalker[0] != L'(') { 468 ShellPrintHiiEx( 469 -1, 470 -1, 471 NULL, 472 STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), 473 gShellLevel1HiiHandle, 474 ArgSet, 475 CurrentScriptFile->CurrentCommand->Line); 476 ShellStatus = SHELL_INVALID_PARAMETER; 477 } else { 478 TempSpot = StrStr(ArgSetWalker, L")"); 479 if (TempSpot != NULL) { 480 TempString = TempSpot+1; 481 if (*(TempString) != CHAR_NULL) { 482 while(TempString != NULL && *TempString == L' ') { 483 TempString++; 484 } 485 if (StrLen(TempString) > 0) { 486 TempSpot = NULL; 487 } 488 } 489 } 490 if (TempSpot == NULL) { 491 ShellPrintHiiEx( 492 -1, 493 -1, 494 NULL, 495 STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), 496 gShellLevel1HiiHandle, 497 CurrentScriptFile->CurrentCommand->Line); 498 ShellStatus = SHELL_INVALID_PARAMETER; 499 } else { 500 *TempSpot = CHAR_NULL; 501 ArgSetWalker++; 502 while (ArgSetWalker != NULL && ArgSetWalker[0] == L' ') { 503 ArgSetWalker++; 504 } 505 if (!ShellIsValidForNumber(ArgSetWalker)) { 506 ShellPrintHiiEx( 507 -1, 508 -1, 509 NULL, 510 STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), 511 gShellLevel1HiiHandle, 512 ArgSet, 513 CurrentScriptFile->CurrentCommand->Line); 514 ShellStatus = SHELL_INVALID_PARAMETER; 515 } else { 516 if (ArgSetWalker[0] == L'-') { 517 Info->Current = 0 - (INTN)ReturnUintn(ArgSetWalker+1); 518 } else { 519 Info->Current = (INTN)ReturnUintn(ArgSetWalker); 520 } 521 ArgSetWalker = StrStr(ArgSetWalker, L" "); 522 while (ArgSetWalker != NULL && ArgSetWalker[0] == L' ') { 523 ArgSetWalker++; 524 } 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->CurrentCommand->Line); 534 ShellStatus = SHELL_INVALID_PARAMETER; 535 } else { 536 if (ArgSetWalker[0] == L'-') { 537 Info->End = 0 - (INTN)ReturnUintn(ArgSetWalker+1); 538 } else { 539 Info->End = (INTN)ReturnUintn(ArgSetWalker); 540 } 541 if (Info->Current < Info->End) { 542 Info->Step = 1; 543 } else { 544 Info->Step = -1; 545 } 546 547 ArgSetWalker = StrStr(ArgSetWalker, L" "); 548 while (ArgSetWalker != NULL && ArgSetWalker[0] == L' ') { 549 ArgSetWalker++; 550 } 551 if (ArgSetWalker != NULL && *ArgSetWalker != CHAR_NULL) { 552 if (ArgSetWalker == NULL || *ArgSetWalker == CHAR_NULL || !ShellIsValidForNumber(ArgSetWalker)){ 553 ShellPrintHiiEx( 554 -1, 555 -1, 556 NULL, 557 STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), 558 gShellLevel1HiiHandle, 559 ArgSet, 560 CurrentScriptFile->CurrentCommand->Line); 561 ShellStatus = SHELL_INVALID_PARAMETER; 562 } else { 563 if (*ArgSetWalker == L')') { 564 ASSERT(Info->Step == 1 || Info->Step == -1); 565 } else { 566 if (ArgSetWalker[0] == L'-') { 567 Info->Step = 0 - (INTN)ReturnUintn(ArgSetWalker+1); 568 } else { 569 Info->Step = (INTN)ReturnUintn(ArgSetWalker); 570 } 571 572 if (StrStr(ArgSetWalker, L" ") != NULL) { 573 ShellPrintHiiEx( 574 -1, 575 -1, 576 NULL, 577 STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), 578 gShellLevel1HiiHandle, 579 ArgSet, 580 CurrentScriptFile->CurrentCommand->Line); 581 ShellStatus = SHELL_INVALID_PARAMETER; 582 } 583 } 584 } 585 586 } 587 } 588 } 589 } 590 } 591 if (ShellStatus == SHELL_SUCCESS) { 592 if (InternalIsAliasOnList(Info->ReplacementName, &CurrentScriptFile->SubstList)) { 593 Info->RemoveSubstAlias = FALSE; 594 } else { 595 Info->RemoveSubstAlias = TRUE; 596 } 597 } 598 if (CurrentScriptFile->CurrentCommand != NULL) { 599 CurrentScriptFile->CurrentCommand->Data = Info; 600 } 601 } 602 } else { 603 ShellPrintHiiEx( 604 -1, 605 -1, 606 NULL, 607 STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT), 608 gShellLevel1HiiHandle, 609 ArgSet, 610 CurrentScriptFile!=NULL 611 && CurrentScriptFile->CurrentCommand!=NULL 612 ? CurrentScriptFile->CurrentCommand->Line:0); 613 ShellStatus = SHELL_INVALID_PARAMETER; 614 } 615 } else { 616 // 617 // These need to be NULL since they are used to determine if this is the first pass later on... 618 // 619 ASSERT(ArgSetWalker == NULL); 620 ASSERT(ArgSet == NULL); 621 } 622 623 if (CurrentScriptFile != NULL && CurrentScriptFile->CurrentCommand != NULL) { 624 Info = (SHELL_FOR_INFO*)CurrentScriptFile->CurrentCommand->Data; 625 if (CurrentScriptFile->CurrentCommand->Reset) { 626 Info->CurrentValue = (CHAR16*)Info->Set; 627 FirstPass = TRUE; 628 CurrentScriptFile->CurrentCommand->Reset = FALSE; 629 } 630 } else { 631 ShellStatus = SHELL_UNSUPPORTED; 632 Info = NULL; 633 } 634 if (ShellStatus == SHELL_SUCCESS) { 635 ASSERT(Info != NULL); 636 if (Info->Step != 0) { 637 // 638 // only advance if not the first pass 639 // 640 if (!FirstPass) { 641 // 642 // sequence version of for loop... 643 // 644 Info->Current += Info->Step; 645 } 646 647 TempString = AllocateZeroPool(50*sizeof(CHAR16)); 648 UnicodeSPrint(TempString, 50*sizeof(CHAR16), L"%d", Info->Current); 649 InternalUpdateAliasOnList(Info->ReplacementName, TempString, &CurrentScriptFile->SubstList); 650 FreePool(TempString); 651 652 if ((Info->Step > 0 && Info->Current > Info->End) || (Info->Step < 0 && Info->Current < Info->End)) { 653 CurrentScriptFile->CurrentCommand->Data = NULL; 654 // 655 // find the matching endfor (we're done with the loop) 656 // 657 if (!MoveToTag(GetNextNode, L"endfor", L"for", NULL, CurrentScriptFile, TRUE, FALSE, FALSE)) { 658 ShellPrintHiiEx( 659 -1, 660 -1, 661 NULL, 662 STRING_TOKEN (STR_SYNTAX_NO_MATCHING), 663 gShellLevel1HiiHandle, 664 L"EndFor", 665 L"For", 666 CurrentScriptFile!=NULL 667 && CurrentScriptFile->CurrentCommand!=NULL 668 ? CurrentScriptFile->CurrentCommand->Line:0); 669 ShellStatus = SHELL_DEVICE_ERROR; 670 } 671 if (Info->RemoveSubstAlias) { 672 // 673 // remove item from list 674 // 675 InternalRemoveAliasFromList(Info->ReplacementName, &CurrentScriptFile->SubstList); 676 } 677 FreePool(Info); 678 } 679 } else { 680 // 681 // Must be in 'in' version of for loop... 682 // 683 ASSERT(Info->Set != NULL); 684 if (Info->CurrentValue != NULL && *Info->CurrentValue != CHAR_NULL) { 685 if (Info->CurrentValue[0] == L' ') { 686 Info->CurrentValue++; 687 } 688 if (Info->CurrentValue[0] == L'\"') { 689 Info->CurrentValue++; 690 } 691 // 692 // do the next one of the set 693 // 694 ASSERT(TempString == NULL); 695 TempString = StrnCatGrow(&TempString, NULL, Info->CurrentValue, 0); 696 if (TempString == NULL) { 697 ShellStatus = SHELL_OUT_OF_RESOURCES; 698 } else { 699 TempSpot = StrStr(TempString, L"\" \""); 700 if (TempSpot != NULL) { 701 *TempSpot = CHAR_NULL; 702 } 703 while (TempString[StrLen(TempString)-1] == L'\"') { 704 TempString[StrLen(TempString)-1] = CHAR_NULL; 705 } 706 InternalUpdateAliasOnList(Info->ReplacementName, TempString, &CurrentScriptFile->SubstList); 707 Info->CurrentValue += StrLen(TempString); 708 709 if (Info->CurrentValue[0] == L'\"') { 710 Info->CurrentValue++; 711 } 712 FreePool(TempString); 713 } 714 } else { 715 CurrentScriptFile->CurrentCommand->Data = NULL; 716 // 717 // find the matching endfor (we're done with the loop) 718 // 719 if (!MoveToTag(GetNextNode, L"endfor", L"for", NULL, CurrentScriptFile, TRUE, FALSE, FALSE)) { 720 ShellPrintHiiEx( 721 -1, 722 -1, 723 NULL, 724 STRING_TOKEN (STR_SYNTAX_NO_MATCHING), 725 gShellLevel1HiiHandle, 726 L"EndFor", 727 L"For", 728 CurrentScriptFile!=NULL 729 && CurrentScriptFile->CurrentCommand!=NULL 730 ? CurrentScriptFile->CurrentCommand->Line:0); 731 ShellStatus = SHELL_DEVICE_ERROR; 732 } 733 if (Info->RemoveSubstAlias) { 734 // 735 // remove item from list 736 // 737 InternalRemoveAliasFromList(Info->ReplacementName, &CurrentScriptFile->SubstList); 738 } 739 FreePool(Info); 740 } 741 } 742 } 743 if (ArgSet != NULL) { 744 FreePool(ArgSet); 745 } 746 return (ShellStatus); 747 } 748 749