• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Main file for If and else shell level 1 function.
3 
4   (C) Copyright 2013-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 typedef enum {
20   EndTagOr,
21   EndTagAnd,
22   EndTagThen,
23   EndTagMax
24 } END_TAG_TYPE;
25 
26 typedef enum {
27   OperatorGreaterThan,
28   OperatorLessThan,
29   OperatorEqual,
30   OperatorNotEqual,
31   OperatorGreatorOrEqual,
32   OperatorLessOrEqual,
33   OperatorUnisgnedGreaterThan,
34   OperatorUnsignedLessThan,
35   OperatorUnsignedGreaterOrEqual,
36   OperatorUnsignedLessOrEqual,
37   OperatorMax
38 } BIN_OPERATOR_TYPE;
39 
40 /**
41   Extract the next fragment, if there is one.
42 
43   @param[in, out] Statement    The current remaining statement.
44   @param[in] Fragment          The current fragment.
45 
46   @retval FALSE   There is not another fragment.
47   @retval TRUE    There is another fragment.
48 **/
49 BOOLEAN
50 EFIAPI
IsNextFragment(IN OUT CONST CHAR16 ** Statement,IN CONST CHAR16 * Fragment)51 IsNextFragment (
52   IN OUT CONST CHAR16     **Statement,
53   IN CONST CHAR16         *Fragment
54   )
55 {
56   CHAR16                  *Tester;
57 
58   Tester = NULL;
59 
60   Tester = StrnCatGrow(&Tester, NULL, *Statement, StrLen(Fragment));
61   ASSERT(Tester != NULL);
62   Tester[StrLen(Fragment)] = CHAR_NULL;
63   if (gUnicodeCollation->StriColl(
64         gUnicodeCollation,
65         (CHAR16*)Fragment,
66         Tester) == 0) {
67     //
68     // increment the string pointer to the end of what we found and then chop off spaces...
69     //
70     *Statement+=StrLen(Fragment);
71     while (*Statement[0] == L' ') {
72       (*Statement)++;
73     }
74     FreePool(Tester);
75     return (TRUE);
76   }
77   FreePool(Tester);
78   return (FALSE);
79 }
80 
81 /**
82   Determine if String represents a valid profile.
83 
84   @param[in] String     The pointer to the string to test.
85 
86   @retval TRUE    String is a valid profile.
87   @retval FALSE   String is not a valid profile.
88 **/
89 BOOLEAN
90 EFIAPI
IsValidProfile(IN CONST CHAR16 * String)91 IsValidProfile (
92   IN CONST CHAR16 *String
93   )
94 {
95   CONST CHAR16  *ProfilesString;
96   CONST CHAR16  *TempLocation;
97 
98   ProfilesString = ShellGetEnvironmentVariable(L"profiles");
99   ASSERT(ProfilesString != NULL);
100   TempLocation = StrStr(ProfilesString, String);
101   if ((TempLocation != NULL) && (*(TempLocation-1) == L';') && (*(TempLocation+StrLen(String)) == L';')) {
102     return (TRUE);
103   }
104   return (FALSE);
105 }
106 
107 /**
108   Do a comparison between 2 things.
109 
110   @param[in] Compare1           The first item to compare.
111   @param[in] Compare2           The second item to compare.
112   @param[in] BinOp              The type of comparison to perform.
113   @param[in] CaseInsensitive    TRUE to do non-case comparison, FALSE otherwise.
114   @param[in] ForceStringCompare TRUE to force string comparison, FALSE otherwise.
115 
116   @return     The result of the comparison.
117 **/
118 BOOLEAN
119 EFIAPI
TestOperation(IN CONST CHAR16 * Compare1,IN CONST CHAR16 * Compare2,IN CONST BIN_OPERATOR_TYPE BinOp,IN CONST BOOLEAN CaseInsensitive,IN CONST BOOLEAN ForceStringCompare)120 TestOperation (
121   IN CONST CHAR16             *Compare1,
122   IN CONST CHAR16             *Compare2,
123   IN CONST BIN_OPERATOR_TYPE  BinOp,
124   IN CONST BOOLEAN            CaseInsensitive,
125   IN CONST BOOLEAN            ForceStringCompare
126   )
127 {
128   INTN Cmp1;
129   INTN Cmp2;
130 
131   //
132   // "Compare1 BinOp Compare2"
133   //
134   switch (BinOp) {
135   case OperatorUnisgnedGreaterThan:
136   case OperatorGreaterThan:
137     if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {
138       //
139       // string compare
140       //
141       if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) > 0) || (StringCompare(&Compare1, &Compare2) > 0)) {
142         return (TRUE);
143       }
144     } else {
145       //
146       // numeric compare
147       //
148       if (Compare1[0] == L'-') {
149         Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1);
150       } else {
151         Cmp1 = (INTN)ShellStrToUintn(Compare1);
152       }
153       if (Compare2[0] == L'-') {
154         Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1);
155       } else {
156         Cmp2 = (INTN)ShellStrToUintn(Compare2);
157       }
158       if (BinOp == OperatorGreaterThan) {
159         if (Cmp1 > Cmp2) {
160           return (TRUE);
161         }
162       } else {
163         if ((UINTN)Cmp1 > (UINTN)Cmp2) {
164           return (TRUE);
165         }
166       }
167     }
168     return (FALSE);
169   case OperatorUnsignedLessThan:
170   case OperatorLessThan:
171     if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {
172       //
173       // string compare
174       //
175       if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) < 0) || (StringCompare(&Compare1, &Compare2) < 0)) {
176         return (TRUE);
177       }
178     } else {
179       //
180       // numeric compare
181       //
182       if (Compare1[0] == L'-') {
183         Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1);
184       } else {
185         Cmp1 = (INTN)ShellStrToUintn(Compare1);
186       }
187       if (Compare2[0] == L'-') {
188         Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1);
189       } else {
190         Cmp2 = (INTN)ShellStrToUintn(Compare2);
191       }
192       if (BinOp == OperatorLessThan) {
193         if (Cmp1 < Cmp2) {
194           return (TRUE);
195         }
196       } else {
197         if ((UINTN)Cmp1 < (UINTN)Cmp2) {
198           return (TRUE);
199         }
200       }
201 
202     }
203     return (FALSE);
204   case OperatorEqual:
205     if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {
206       //
207       // string compare
208       //
209       if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) == 0) || (StringCompare(&Compare1, &Compare2) == 0)) {
210         return (TRUE);
211       }
212     } else {
213       //
214       // numeric compare
215       //
216       if (Compare1[0] == L'-') {
217         Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1);
218       } else {
219         Cmp1 = (INTN)ShellStrToUintn(Compare1);
220       }
221       if (Compare2[0] == L'-') {
222         Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1);
223       } else {
224         Cmp2 = (INTN)ShellStrToUintn(Compare2);
225       }
226       if (Cmp1 == Cmp2) {
227         return (TRUE);
228       }
229     }
230     return (FALSE);
231   case OperatorNotEqual:
232     if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {
233       //
234       // string compare
235       //
236       if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) != 0) || (StringCompare(&Compare1, &Compare2) != 0)) {
237         return (TRUE);
238       }
239     } else {
240       //
241       // numeric compare
242       //
243       if (Compare1[0] == L'-') {
244         Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1);
245       } else {
246         Cmp1 = (INTN)ShellStrToUintn(Compare1);
247       }
248       if (Compare2[0] == L'-') {
249         Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1);
250       } else {
251         Cmp2 = (INTN)ShellStrToUintn(Compare2);
252       }
253       if (Cmp1 != Cmp2) {
254         return (TRUE);
255       }
256     }
257     return (FALSE);
258   case OperatorUnsignedGreaterOrEqual:
259   case OperatorGreatorOrEqual:
260     if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {
261       //
262       // string compare
263       //
264       if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) >= 0) || (StringCompare(&Compare1, &Compare2) >= 0)) {
265         return (TRUE);
266       }
267     } else {
268       //
269       // numeric compare
270       //
271       if (Compare1[0] == L'-') {
272         Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1);
273       } else {
274         Cmp1 = (INTN)ShellStrToUintn(Compare1);
275       }
276       if (Compare2[0] == L'-') {
277         Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1);
278       } else {
279         Cmp2 = (INTN)ShellStrToUintn(Compare2);
280       }
281       if (BinOp == OperatorGreatorOrEqual) {
282         if (Cmp1 >= Cmp2) {
283           return (TRUE);
284         }
285       } else {
286         if ((UINTN)Cmp1 >= (UINTN)Cmp2) {
287           return (TRUE);
288         }
289       }
290     }
291     return (FALSE);
292   case OperatorLessOrEqual:
293   case OperatorUnsignedLessOrEqual:
294     if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {
295       //
296       // string compare
297       //
298       if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) <= 0) || (StringCompare(&Compare1, &Compare2) <= 0)) {
299         return (TRUE);
300       }
301     } else {
302       //
303       // numeric compare
304       //
305       if (Compare1[0] == L'-') {
306         Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1);
307       } else {
308         Cmp1 = (INTN)ShellStrToUintn(Compare1);
309       }
310       if (Compare2[0] == L'-') {
311         Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1);
312       } else {
313         Cmp2 = (INTN)ShellStrToUintn(Compare2);
314       }
315       if (BinOp == OperatorLessOrEqual) {
316         if (Cmp1 <= Cmp2) {
317           return (TRUE);
318         }
319       } else {
320         if ((UINTN)Cmp1 <= (UINTN)Cmp2) {
321           return (TRUE);
322         }
323       }
324     }
325     return (FALSE);
326   default:
327     ASSERT(FALSE);
328     return (FALSE);
329   }
330 }
331 
332 /**
333   Process an if statement and determine if its is valid or not.
334 
335   @param[in, out] PassingState     Opon entry, the current state.  Upon exit,
336                                    the new state.
337   @param[in] StartParameterNumber  The number of the first parameter of
338                                    this statement.
339   @param[in] EndParameterNumber    The number of the final parameter of
340                                    this statement.
341   @param[in] OperatorToUse         The type of termination operator.
342   @param[in] CaseInsensitive       TRUE for case insensitive, FALSE otherwise.
343   @param[in] ForceStringCompare    TRUE for all string based, FALSE otherwise.
344 
345   @retval EFI_INVALID_PARAMETER   A parameter was invalid.
346   @retval EFI_SUCCESS             The operation was successful.
347 **/
348 EFI_STATUS
349 EFIAPI
ProcessStatement(IN OUT BOOLEAN * PassingState,IN UINTN StartParameterNumber,IN UINTN EndParameterNumber,IN CONST END_TAG_TYPE OperatorToUse,IN CONST BOOLEAN CaseInsensitive,IN CONST BOOLEAN ForceStringCompare)350 ProcessStatement (
351   IN OUT BOOLEAN          *PassingState,
352   IN UINTN                StartParameterNumber,
353   IN UINTN                EndParameterNumber,
354   IN CONST END_TAG_TYPE   OperatorToUse,
355   IN CONST BOOLEAN        CaseInsensitive,
356   IN CONST BOOLEAN        ForceStringCompare
357   )
358 {
359   EFI_STATUS              Status;
360   BOOLEAN                 OperationResult;
361   BOOLEAN                 NotPresent;
362   CHAR16                  *StatementWalker;
363   BIN_OPERATOR_TYPE       BinOp;
364   CHAR16                  *Compare1;
365   CHAR16                  *Compare2;
366   CHAR16                  HexString[20];
367   CHAR16                  *TempSpot;
368 
369   ASSERT((END_TAG_TYPE)OperatorToUse != EndTagThen);
370 
371   Status          = EFI_SUCCESS;
372   BinOp           = OperatorMax;
373   OperationResult = FALSE;
374   StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber];
375   if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"not")) {
376     NotPresent      = TRUE;
377     StatementWalker = gEfiShellParametersProtocol->Argv[++StartParameterNumber];
378   } else {
379     NotPresent = FALSE;
380   }
381 
382   //
383   // now check for 'boolfunc' operators
384   //
385   if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"isint")) {
386     if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && StatementWalker[StrLen(StatementWalker)-1] == L')') {
387       StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL;
388       OperationResult = ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE);
389     } else {
390       Status = EFI_INVALID_PARAMETER;
391       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"isint");
392     }
393   } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"exists") || IsNextFragment((CONST CHAR16**)(&StatementWalker), L"exist")) {
394     if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && StatementWalker[StrLen(StatementWalker)-1] == L')') {
395       StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL;
396       //
397       // is what remains a file in CWD???
398       //
399       OperationResult = (BOOLEAN)(ShellFileExists(StatementWalker)==EFI_SUCCESS);
400     } else if (StatementWalker[0] == CHAR_NULL && StartParameterNumber+1 == EndParameterNumber) {
401       OperationResult = (BOOLEAN)(ShellFileExists(gEfiShellParametersProtocol->Argv[++StartParameterNumber])==EFI_SUCCESS);
402     } else {
403       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"exist(s)");
404       Status = EFI_INVALID_PARAMETER;
405     }
406   } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"available")) {
407     if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && StatementWalker[StrLen(StatementWalker)-1] == L')') {
408       StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL;
409       //
410       // is what remains a file in the CWD or path???
411       //
412       OperationResult = (BOOLEAN)(ShellIsFileInPath(StatementWalker)==EFI_SUCCESS);
413     } else {
414       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"available");
415       Status = EFI_INVALID_PARAMETER;
416     }
417   } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"profile")) {
418     if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && StatementWalker[StrLen(StatementWalker)-1] == L')') {
419       //
420       // Chop off that ')'
421       //
422       StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL;
423       OperationResult = IsValidProfile(StatementWalker);
424     } else {
425       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"profile");
426       Status = EFI_INVALID_PARAMETER;
427     }
428   } else if (StartParameterNumber+1 >= EndParameterNumber) {
429       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[StartParameterNumber]);
430       Status = EFI_INVALID_PARAMETER;
431   } else {
432     //
433     // must be 'item binop item' style
434     //
435     Compare1 = NULL;
436     Compare2 = NULL;
437     BinOp    = OperatorMax;
438 
439     //
440     // get the first item
441     //
442     StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber];
443     if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"efierror")) {
444       TempSpot = StrStr(StatementWalker, L")");
445       if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) {
446         *TempSpot = CHAR_NULL;
447         if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
448           UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT);
449           ASSERT(Compare1 == NULL);
450           Compare1 = StrnCatGrow(&Compare1, NULL, HexString, 0);
451           StatementWalker += StrLen(StatementWalker) + 1;
452         } else {
453           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");
454           Status = EFI_INVALID_PARAMETER;
455         }
456       } else {
457         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");
458         Status = EFI_INVALID_PARAMETER;
459       }
460     } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"pierror")) {
461       TempSpot = StrStr(StatementWalker, L")");
462       if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) {
463         *TempSpot = CHAR_NULL;
464         if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
465           UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>2));
466           ASSERT(Compare1 == NULL);
467           Compare1 = StrnCatGrow(&Compare1, NULL, HexString, 0);
468           StatementWalker += StrLen(StatementWalker) + 1;
469         } else {
470           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");
471           Status = EFI_INVALID_PARAMETER;
472         }
473       } else {
474         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");
475         Status = EFI_INVALID_PARAMETER;
476       }
477     } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"oemerror")) {
478       TempSpot = StrStr(StatementWalker, L")");
479       if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) {
480         TempSpot = CHAR_NULL;
481         if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
482           UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>1));
483           ASSERT(Compare1 == NULL);
484           Compare1 = StrnCatGrow(&Compare1, NULL, HexString, 0);
485           StatementWalker += StrLen(StatementWalker) + 1;
486         } else {
487           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");
488           Status = EFI_INVALID_PARAMETER;
489         }
490       } else {
491         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");
492         Status = EFI_INVALID_PARAMETER;
493       }
494     } else {
495       ASSERT(Compare1 == NULL);
496       if (EndParameterNumber - StartParameterNumber > 2) {
497           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_STARTING), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[StartParameterNumber+2]);
498           Status = EFI_INVALID_PARAMETER;
499       } else {
500         //
501         // must be a raw string
502         //
503         Compare1 = StrnCatGrow(&Compare1, NULL, StatementWalker, 0);
504       }
505     }
506 
507     //
508     // get the operator
509     //
510     ASSERT(StartParameterNumber+1<EndParameterNumber);
511     StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber+1];
512     if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"gt")) {
513       BinOp = OperatorGreaterThan;
514     } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"lt")) {
515       BinOp = OperatorLessThan;
516     } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"eq")) {
517       BinOp = OperatorEqual;
518     } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ne")) {
519       BinOp = OperatorNotEqual;
520     } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ge")) {
521       BinOp = OperatorGreatorOrEqual;
522     } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"le")) {
523       BinOp = OperatorLessOrEqual;
524     } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"==")) {
525       BinOp = OperatorEqual;
526     } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ugt")) {
527       BinOp = OperatorUnisgnedGreaterThan;
528     } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ult")) {
529       BinOp = OperatorUnsignedLessThan;
530     } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"uge")) {
531       BinOp = OperatorUnsignedGreaterOrEqual;
532     } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ule")) {
533       BinOp = OperatorUnsignedLessOrEqual;
534     } else {
535       ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_INVALID_BINOP), gShellLevel1HiiHandle, StatementWalker);
536       Status = EFI_INVALID_PARAMETER;
537     }
538 
539     //
540     // get the second item
541     //
542     ASSERT(StartParameterNumber+2<=EndParameterNumber);
543     StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber+2];
544     if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"efierror")) {
545       TempSpot = StrStr(StatementWalker, L")");
546       if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) {
547         TempSpot = CHAR_NULL;
548         if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
549           UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT);
550           ASSERT(Compare2 == NULL);
551           Compare2 = StrnCatGrow(&Compare2, NULL, HexString, 0);
552           StatementWalker += StrLen(StatementWalker) + 1;
553         } else {
554           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");
555           Status = EFI_INVALID_PARAMETER;
556         }
557       } else {
558         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");
559         Status = EFI_INVALID_PARAMETER;
560       }
561     //
562     // can this be collapsed into the above?
563     //
564     } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"pierror")) {
565       TempSpot = StrStr(StatementWalker, L")");
566       if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) {
567         TempSpot = CHAR_NULL;
568         if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
569           UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>2));
570           ASSERT(Compare2 == NULL);
571           Compare2 = StrnCatGrow(&Compare2, NULL, HexString, 0);
572           StatementWalker += StrLen(StatementWalker) + 1;
573         } else {
574           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");
575           Status = EFI_INVALID_PARAMETER;
576         }
577       } else {
578         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");
579         Status = EFI_INVALID_PARAMETER;
580       }
581     } else if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"oemerror")) {
582       TempSpot = StrStr(StatementWalker, L")");
583       if (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(") && TempSpot != NULL) {
584         TempSpot = CHAR_NULL;
585         if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
586           UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>1));
587           ASSERT(Compare2 == NULL);
588           Compare2 = StrnCatGrow(&Compare2, NULL, HexString, 0);
589           StatementWalker += StrLen(StatementWalker) + 1;
590         } else {
591           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");
592           Status = EFI_INVALID_PARAMETER;
593         }
594       } else {
595         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");
596         Status = EFI_INVALID_PARAMETER;
597       }
598     } else {
599       //
600       // must be a raw string
601       //
602       ASSERT(Compare2 == NULL);
603       Compare2 = StrnCatGrow(&Compare2, NULL, StatementWalker, 0);
604     }
605 
606     if (Compare1 != NULL && Compare2 != NULL && BinOp != OperatorMax) {
607       OperationResult = TestOperation(Compare1, Compare2, BinOp, CaseInsensitive, ForceStringCompare);
608     }
609 
610     SHELL_FREE_NON_NULL(Compare1);
611     SHELL_FREE_NON_NULL(Compare2);
612   }
613 
614   //
615   // done processing do result...
616   //
617 
618   if (!EFI_ERROR(Status)) {
619     if (NotPresent) {
620       OperationResult = (BOOLEAN)(!OperationResult);
621     }
622     switch(OperatorToUse) {
623       case EndTagOr:
624         *PassingState = (BOOLEAN)(*PassingState || OperationResult);
625         break;
626       case EndTagAnd:
627         *PassingState = (BOOLEAN)(*PassingState && OperationResult);
628         break;
629       case EndTagMax:
630         *PassingState = (BOOLEAN)(OperationResult);
631         break;
632       default:
633         ASSERT(FALSE);
634     }
635   }
636   return (Status);
637 }
638 
639 /**
640   Break up the next part of the if statement (until the next 'and', 'or', or 'then').
641 
642   @param[in] ParameterNumber      The current parameter number.
643   @param[out] EndParameter        Upon successful return, will point to the
644                                   parameter to start the next iteration with.
645   @param[out] EndTag              Upon successful return, will point to the
646                                   type that was found at the end of this statement.
647 
648   @retval TRUE    A valid statement was found.
649   @retval FALSE   A valid statement was not found.
650 **/
651 BOOLEAN
652 EFIAPI
BuildNextStatement(IN UINTN ParameterNumber,OUT UINTN * EndParameter,OUT END_TAG_TYPE * EndTag)653 BuildNextStatement (
654   IN UINTN          ParameterNumber,
655   OUT UINTN         *EndParameter,
656   OUT END_TAG_TYPE  *EndTag
657   )
658 {
659   *EndTag = EndTagMax;
660 
661   for(
662     ; ParameterNumber < gEfiShellParametersProtocol->Argc
663     ; ParameterNumber++
664    ) {
665     if (gUnicodeCollation->StriColl(
666           gUnicodeCollation,
667           gEfiShellParametersProtocol->Argv[ParameterNumber],
668           L"or") == 0) {
669       *EndParameter = ParameterNumber - 1;
670       *EndTag = EndTagOr;
671       break;
672     } else if (gUnicodeCollation->StriColl(
673           gUnicodeCollation,
674           gEfiShellParametersProtocol->Argv[ParameterNumber],
675           L"and") == 0) {
676       *EndParameter = ParameterNumber - 1;
677       *EndTag = EndTagAnd;
678       break;
679     } else if (gUnicodeCollation->StriColl(
680           gUnicodeCollation,
681           gEfiShellParametersProtocol->Argv[ParameterNumber],
682           L"then") == 0) {
683       *EndParameter = ParameterNumber - 1;
684       *EndTag = EndTagThen;
685       break;
686     }
687   }
688   if (*EndTag == EndTagMax) {
689     return (FALSE);
690   }
691   return (TRUE);
692 }
693 
694 /**
695   Move the script file pointer to a different place in the script file.
696   This one is special since it handles the if/else/endif syntax.
697 
698   @param[in] ScriptFile     The script file from GetCurrnetScriptFile().
699 
700   @retval TRUE     The move target was found and the move was successful.
701   @retval FALSE    Something went wrong.
702 **/
703 BOOLEAN
704 EFIAPI
MoveToTagSpecial(IN SCRIPT_FILE * ScriptFile)705 MoveToTagSpecial (
706   IN SCRIPT_FILE                *ScriptFile
707   )
708 {
709   SCRIPT_COMMAND_LIST *CommandNode;
710   BOOLEAN             Found;
711   UINTN               TargetCount;
712   CHAR16              *CommandName;
713   CHAR16              *CommandWalker;
714   CHAR16              *TempLocation;
715 
716   TargetCount         = 1;
717   Found               = FALSE;
718 
719   if (ScriptFile == NULL) {
720     return FALSE;
721   }
722 
723   for (CommandNode = (SCRIPT_COMMAND_LIST *)GetNextNode(&ScriptFile->CommandList, &ScriptFile->CurrentCommand->Link), Found = FALSE
724     ;  !IsNull(&ScriptFile->CommandList, &CommandNode->Link) && !Found
725     ;  CommandNode = (SCRIPT_COMMAND_LIST *)GetNextNode(&ScriptFile->CommandList, &CommandNode->Link)
726    ){
727 
728     //
729     // get just the first part of the command line...
730     //
731     CommandName   = NULL;
732     CommandName   = StrnCatGrow(&CommandName, NULL, CommandNode->Cl, 0);
733     if (CommandName == NULL) {
734       continue;
735     }
736     CommandWalker = CommandName;
737 
738     //
739     // Skip leading spaces and tabs.
740     //
741     while ((CommandWalker[0] == L' ') || (CommandWalker[0] == L'\t')) {
742       CommandWalker++;
743     }
744     TempLocation  = StrStr(CommandWalker, L" ");
745 
746     if (TempLocation != NULL) {
747       *TempLocation = CHAR_NULL;
748     }
749 
750     //
751     // did we find a nested item ?
752     //
753     if (gUnicodeCollation->StriColl(
754         gUnicodeCollation,
755         (CHAR16*)CommandWalker,
756         L"If") == 0) {
757       TargetCount++;
758     } else if (TargetCount == 1 && gUnicodeCollation->StriColl(
759         gUnicodeCollation,
760         (CHAR16*)CommandWalker,
761         (CHAR16*)L"else") == 0) {
762       //
763       // else can only decrement the last part... not an nested if
764       // hence the TargetCount compare added
765       //
766       TargetCount--;
767     } else if (gUnicodeCollation->StriColl(
768         gUnicodeCollation,
769         (CHAR16*)CommandWalker,
770         (CHAR16*)L"endif") == 0) {
771       TargetCount--;
772     }
773     if (TargetCount == 0) {
774       ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetNextNode(&ScriptFile->CommandList, &CommandNode->Link);
775       Found = TRUE;
776     }
777 
778     //
779     // Free the memory for this loop...
780     //
781     SHELL_FREE_NON_NULL(CommandName);
782   }
783   return (Found);
784 }
785 
786 /**
787   Deal with the result of the if operation.
788 
789   @param[in] Result     The result of the if.
790 
791   @retval EFI_SUCCESS       The operation was successful.
792   @retval EFI_NOT_FOUND     The ending tag could not be found.
793 **/
794 EFI_STATUS
795 EFIAPI
PerformResultOperation(IN CONST BOOLEAN Result)796 PerformResultOperation (
797   IN CONST BOOLEAN Result
798   )
799 {
800   if (Result || MoveToTagSpecial(ShellCommandGetCurrentScriptFile())) {
801     return (EFI_SUCCESS);
802   }
803   return (EFI_NOT_FOUND);
804 }
805 
806 /**
807   Function for 'if' command.
808 
809   @param[in] ImageHandle  Handle to the Image (NULL if Internal).
810   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
811 **/
812 SHELL_STATUS
813 EFIAPI
ShellCommandRunIf(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)814 ShellCommandRunIf (
815   IN EFI_HANDLE        ImageHandle,
816   IN EFI_SYSTEM_TABLE  *SystemTable
817   )
818 {
819   EFI_STATUS          Status;
820   SHELL_STATUS        ShellStatus;
821   BOOLEAN             CaseInsensitive;
822   BOOLEAN             ForceString;
823   UINTN               CurrentParameter;
824   UINTN               EndParameter;
825   BOOLEAN             CurrentValue;
826   END_TAG_TYPE        Ending;
827   END_TAG_TYPE        PreviousEnding;
828   SCRIPT_FILE         *CurrentScriptFile;
829 
830   Status = CommandInit();
831   ASSERT_EFI_ERROR(Status);
832 
833   if (!gEfiShellProtocol->BatchIsActive()) {
834     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"if");
835     return (SHELL_UNSUPPORTED);
836   }
837 
838   if (gEfiShellParametersProtocol->Argc < 3) {
839     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel1HiiHandle, L"if");
840     return (SHELL_INVALID_PARAMETER);
841   }
842 
843   //
844   // Make sure that an End exists.
845   //
846   CurrentScriptFile = ShellCommandGetCurrentScriptFile();
847   if (!MoveToTag(GetNextNode, L"endif", L"if", NULL, CurrentScriptFile, TRUE, TRUE, FALSE)) {
848     ShellPrintHiiEx(
849       -1,
850       -1,
851       NULL,
852       STRING_TOKEN (STR_SYNTAX_NO_MATCHING),
853       gShellLevel1HiiHandle,
854       L"EndIf",
855       L"If",
856       CurrentScriptFile!=NULL
857         && CurrentScriptFile->CurrentCommand!=NULL
858         ? CurrentScriptFile->CurrentCommand->Line:0);
859     return (SHELL_DEVICE_ERROR);
860   }
861 
862   //
863   // initialize the shell lib (we must be in non-auto-init...)
864   //
865   Status = ShellInitialize();
866   ASSERT_EFI_ERROR(Status);
867 
868   CurrentParameter    = 1;
869   EndParameter        = 0;
870 
871   if (gUnicodeCollation->StriColl(
872         gUnicodeCollation,
873         gEfiShellParametersProtocol->Argv[1],
874         L"/i") == 0 ||
875       gUnicodeCollation->StriColl(
876         gUnicodeCollation,
877         gEfiShellParametersProtocol->Argv[2],
878         L"/i") == 0 ||
879       (gEfiShellParametersProtocol->Argc > 3 && gUnicodeCollation->StriColl(
880         gUnicodeCollation,
881         gEfiShellParametersProtocol->Argv[3],
882         L"/i") == 0)) {
883     CaseInsensitive = TRUE;
884     CurrentParameter++;
885   } else {
886     CaseInsensitive = FALSE;
887   }
888   if (gUnicodeCollation->StriColl(
889         gUnicodeCollation,
890         gEfiShellParametersProtocol->Argv[1],
891         L"/s") == 0 ||
892       gUnicodeCollation->StriColl(
893         gUnicodeCollation,
894         gEfiShellParametersProtocol->Argv[2],
895         L"/s") == 0 ||
896       (gEfiShellParametersProtocol->Argc > 3 && gUnicodeCollation->StriColl(
897         gUnicodeCollation,
898         gEfiShellParametersProtocol->Argv[3],
899         L"/s") == 0)) {
900     ForceString     = TRUE;
901     CurrentParameter++;
902   } else {
903     ForceString     = FALSE;
904   }
905 
906   for ( ShellStatus = SHELL_SUCCESS, CurrentValue = FALSE, Ending = EndTagMax
907       ; CurrentParameter < gEfiShellParametersProtocol->Argc && ShellStatus == SHELL_SUCCESS
908       ; CurrentParameter++) {
909     if (gUnicodeCollation->StriColl(
910           gUnicodeCollation,
911           gEfiShellParametersProtocol->Argv[CurrentParameter],
912           L"then") == 0) {
913       //
914       // we are at the then
915       //
916       if (CurrentParameter+1 != gEfiShellParametersProtocol->Argc) {
917         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TEXT_AFTER_THEN), gShellLevel1HiiHandle, L"if");
918         ShellStatus = SHELL_INVALID_PARAMETER;
919       } else {
920         Status = PerformResultOperation(CurrentValue);
921         if (EFI_ERROR(Status)) {
922           ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_AFTER_BAD), gShellLevel1HiiHandle, L"if", gEfiShellParametersProtocol->Argv[CurrentParameter]);
923           ShellStatus = SHELL_INVALID_PARAMETER;
924         }
925       }
926     } else {
927       PreviousEnding = Ending;
928       //
929       // build up the next statement for analysis
930       //
931       if (!BuildNextStatement(CurrentParameter, &EndParameter, &Ending)) {
932         CurrentScriptFile = ShellCommandGetCurrentScriptFile();
933         ShellPrintHiiEx(
934           -1,
935           -1,
936           NULL,
937           STRING_TOKEN (STR_SYNTAX_NO_MATCHING),
938           gShellLevel1HiiHandle,
939           L"Then",
940           L"If",
941           CurrentScriptFile!=NULL
942             && CurrentScriptFile->CurrentCommand!=NULL
943             ? CurrentScriptFile->CurrentCommand->Line:0);
944         ShellStatus = SHELL_INVALID_PARAMETER;
945       } else {
946         //
947         // Analyze the statement
948         //
949         Status = ProcessStatement(&CurrentValue, CurrentParameter, EndParameter, PreviousEnding, CaseInsensitive, ForceString);
950         if (EFI_ERROR(Status)) {
951 //          ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_STARTING), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[CurrentParameter]);
952           ShellStatus = SHELL_INVALID_PARAMETER;
953         } else {
954           //
955           // Optomize to get out of the loop early...
956           //
957           if ((Ending == EndTagOr && CurrentValue) || (Ending == EndTagAnd && !CurrentValue)) {
958             Status = PerformResultOperation(CurrentValue);
959             if (EFI_ERROR(Status)) {
960               ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_AFTER_BAD), gShellLevel1HiiHandle, L"if", gEfiShellParametersProtocol->Argv[CurrentParameter]);
961               ShellStatus = SHELL_INVALID_PARAMETER;
962             }
963             break;
964           }
965         }
966       }
967       if (ShellStatus == SHELL_SUCCESS){
968         CurrentParameter = EndParameter;
969         //
970         // Skip over the or or and parameter.
971         //
972         if (Ending == EndTagOr || Ending == EndTagAnd) {
973           CurrentParameter++;
974         }
975       }
976     }
977   }
978   return (ShellStatus);
979 }
980 
981 /**
982   Function for 'else' command.
983 
984   @param[in] ImageHandle  Handle to the Image (NULL if Internal).
985   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
986 **/
987 SHELL_STATUS
988 EFIAPI
ShellCommandRunElse(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)989 ShellCommandRunElse (
990   IN EFI_HANDLE        ImageHandle,
991   IN EFI_SYSTEM_TABLE  *SystemTable
992   )
993 {
994   SCRIPT_FILE *CurrentScriptFile;
995   ASSERT_EFI_ERROR(CommandInit());
996 
997   if (gEfiShellParametersProtocol->Argc > 1) {
998     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle, L"if");
999     return (SHELL_INVALID_PARAMETER);
1000   }
1001 
1002   if (!gEfiShellProtocol->BatchIsActive()) {
1003     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"Else");
1004     return (SHELL_UNSUPPORTED);
1005   }
1006 
1007   CurrentScriptFile = ShellCommandGetCurrentScriptFile();
1008 
1009   if (!MoveToTag(GetPreviousNode, L"if", L"endif", NULL, CurrentScriptFile, FALSE, TRUE, FALSE)) {
1010     ShellPrintHiiEx(
1011       -1,
1012       -1,
1013       NULL,
1014       STRING_TOKEN (STR_SYNTAX_NO_MATCHING),
1015       gShellLevel1HiiHandle,
1016       L"If",
1017       L"Else",
1018       CurrentScriptFile!=NULL
1019         && CurrentScriptFile->CurrentCommand!=NULL
1020         ? CurrentScriptFile->CurrentCommand->Line:0);
1021     return (SHELL_DEVICE_ERROR);
1022   }
1023   if (!MoveToTag(GetPreviousNode, L"if", L"else", NULL, CurrentScriptFile, FALSE, TRUE, FALSE)) {
1024     ShellPrintHiiEx(
1025       -1,
1026       -1,
1027       NULL,
1028       STRING_TOKEN (STR_SYNTAX_NO_MATCHING),
1029       gShellLevel1HiiHandle,
1030       L"If",
1031       L"Else",
1032       CurrentScriptFile!=NULL
1033         && CurrentScriptFile->CurrentCommand!=NULL
1034         ? CurrentScriptFile->CurrentCommand->Line:0);
1035     return (SHELL_DEVICE_ERROR);
1036   }
1037 
1038   if (!MoveToTag(GetNextNode, L"endif", L"if", NULL, CurrentScriptFile, FALSE, FALSE, FALSE)) {
1039     ShellPrintHiiEx(
1040       -1,
1041       -1,
1042       NULL,
1043       STRING_TOKEN (STR_SYNTAX_NO_MATCHING),
1044       gShellLevel1HiiHandle,
1045       L"EndIf",
1046       "Else",
1047       CurrentScriptFile!=NULL
1048         && CurrentScriptFile->CurrentCommand!=NULL
1049         ? CurrentScriptFile->CurrentCommand->Line:0);
1050     return (SHELL_DEVICE_ERROR);
1051   }
1052 
1053   return (SHELL_SUCCESS);
1054 }
1055 
1056 /**
1057   Function for 'endif' command.
1058 
1059   @param[in] ImageHandle  Handle to the Image (NULL if Internal).
1060   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).
1061 **/
1062 SHELL_STATUS
1063 EFIAPI
ShellCommandRunEndIf(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)1064 ShellCommandRunEndIf (
1065   IN EFI_HANDLE        ImageHandle,
1066   IN EFI_SYSTEM_TABLE  *SystemTable
1067   )
1068 {
1069   SCRIPT_FILE *CurrentScriptFile;
1070   ASSERT_EFI_ERROR(CommandInit());
1071 
1072   if (gEfiShellParametersProtocol->Argc > 1) {
1073     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle, L"if");
1074     return (SHELL_INVALID_PARAMETER);
1075   }
1076 
1077   if (!gEfiShellProtocol->BatchIsActive()) {
1078     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"Endif");
1079     return (SHELL_UNSUPPORTED);
1080   }
1081 
1082   CurrentScriptFile = ShellCommandGetCurrentScriptFile();
1083   if (!MoveToTag(GetPreviousNode, L"if", L"endif", NULL, CurrentScriptFile, FALSE, TRUE, FALSE)) {
1084     ShellPrintHiiEx(
1085       -1,
1086       -1,
1087       NULL,
1088       STRING_TOKEN (STR_SYNTAX_NO_MATCHING),
1089       gShellLevel1HiiHandle,
1090       L"If",
1091       L"EndIf",
1092       CurrentScriptFile!=NULL
1093         && CurrentScriptFile->CurrentCommand!=NULL
1094         ? CurrentScriptFile->CurrentCommand->Line:0);
1095     return (SHELL_DEVICE_ERROR);
1096   }
1097 
1098   return (SHELL_SUCCESS);
1099 }
1100