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