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