2 EFI tools utility functions to display warning, error, and informational messages
4 Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 #include "EfiUtilityMsgs.h"
24 // Declare module globals for keeping track of the the utility's
25 // name and other settings.
27 STATIC STATUS mStatus
= STATUS_SUCCESS
;
28 STATIC CHAR8 mUtilityName
[50] = { 0 };
29 STATIC UINT64 mPrintLogLevel
= INFO_LOG_LEVEL
;
30 STATIC CHAR8
*mSourceFileName
= NULL
;
31 STATIC UINT32 mSourceFileLineNum
= 0;
32 STATIC UINT32 mErrorCount
= 0;
33 STATIC UINT32 mWarningCount
= 0;
34 STATIC UINT32 mMaxErrors
= 0;
35 STATIC UINT32 mMaxWarnings
= 0;
36 STATIC UINT32 mMaxWarningsPlusErrors
= 0;
37 STATIC INT8 mPrintLimitsSet
= 0;
57 Prints an error message.
60 All arguments are optional, though the printed message may be useless if
61 at least something valid is not specified.
63 FileName - name of the file or application. If not specified, then the
64 utilty name (as set by the utility calling SetUtilityName()
65 earlier) is used. Otherwise "Unknown utility" is used.
67 LineNumber - the line number of error, typically used by parsers. If the
68 utility is not a parser, then 0 should be specified. Otherwise
69 the FileName and LineNumber info can be used to cause
70 MS Visual Studio to jump to the error.
72 MessageCode - an application-specific error code that can be referenced in
75 Text - the text in question, typically used by parsers.
77 MsgFmt - the format string for the error message. Can contain formatting
78 controls for use with the varargs.
84 We print the following (similar to the Warn() and Debug()
86 Typical error/warning message format:
88 bin\VfrCompile.cpp(330) : error C2660: 'AddVfrDataStructField' : function does not take 2 parameters
90 BUGBUG -- these three utility functions are almost identical, and
91 should be modified to share code.
93 Visual Studio does not find error messages with:
107 // If limits have been set, then check that we have not exceeded them
109 if (mPrintLimitsSet
) {
111 // See if we've exceeded our total count
113 if (mMaxWarningsPlusErrors
!= 0) {
114 if (mErrorCount
+ mWarningCount
> mMaxWarningsPlusErrors
) {
115 PrintLimitExceeded ();
120 // See if we've exceeded our error count
122 if (mMaxErrors
!= 0) {
123 if (mErrorCount
> mMaxErrors
) {
124 PrintLimitExceeded ();
131 va_start (List
, MsgFmt
);
132 PrintMessage ("ERROR", FileName
, LineNumber
, MessageCode
, Text
, MsgFmt
, List
);
146 Print a parser error, using the source file name and line number
147 set by a previous call to SetParserPosition().
150 MessageCode - application-specific error code
151 Text - text to print in the error message
152 MsgFmt - format string to print at the end of the error message
161 // If limits have been set, then check them
163 if (mPrintLimitsSet
) {
165 // See if we've exceeded our total count
167 if (mMaxWarningsPlusErrors
!= 0) {
168 if (mErrorCount
+ mWarningCount
> mMaxWarningsPlusErrors
) {
169 PrintLimitExceeded ();
174 // See if we've exceeded our error count
176 if (mMaxErrors
!= 0) {
177 if (mErrorCount
> mMaxErrors
) {
178 PrintLimitExceeded ();
185 va_start (List
, MsgFmt
);
186 PrintMessage ("ERROR", mSourceFileName
, mSourceFileLineNum
, MessageCode
, Text
, MsgFmt
, List
);
193 CHAR8
*OffendingText
,
200 Print a parser warning, using the source file name and line number
201 set by a previous call to SetParserPosition().
204 ErrorCode - application-specific error code
205 OffendingText - text to print in the warning message
206 MsgFmt - format string to print at the end of the warning message
215 // If limits have been set, then check them
217 if (mPrintLimitsSet
) {
219 // See if we've exceeded our total count
221 if (mMaxWarningsPlusErrors
!= 0) {
222 if (mErrorCount
+ mWarningCount
> mMaxWarningsPlusErrors
) {
223 PrintLimitExceeded ();
228 // See if we've exceeded our warning count
230 if (mMaxWarnings
!= 0) {
231 if (mWarningCount
> mMaxWarnings
) {
232 PrintLimitExceeded ();
239 va_start (List
, MsgFmt
);
240 PrintMessage ("WARNING", mSourceFileName
, mSourceFileLineNum
, ErrorCode
, OffendingText
, MsgFmt
, List
);
243 // Don't set warning status accordingly
245 // if (mStatus < STATUS_WARNING) {
246 // mStatus = STATUS_WARNING;
262 Print a warning message.
265 FileName - name of the file where the warning was detected, or the name
266 of the application that detected the warning
268 LineNumber - the line number where the warning was detected (parsers).
269 0 should be specified if the utility is not a parser.
271 MessageCode - an application-specific warning code that can be referenced in
274 Text - the text in question (parsers)
276 MsgFmt - the format string for the warning message. Can contain formatting
277 controls for use with varargs.
287 // Current Print Level not output warning information.
289 if (WARNING_LOG_LEVEL
< mPrintLogLevel
) {
293 // If limits have been set, then check them
295 if (mPrintLimitsSet
) {
297 // See if we've exceeded our total count
299 if (mMaxWarningsPlusErrors
!= 0) {
300 if (mErrorCount
+ mWarningCount
> mMaxWarningsPlusErrors
) {
301 PrintLimitExceeded ();
306 // See if we've exceeded our warning count
308 if (mMaxWarnings
!= 0) {
309 if (mWarningCount
> mMaxWarnings
) {
310 PrintLimitExceeded ();
317 va_start (List
, MsgFmt
);
318 PrintMessage ("WARNING", FileName
, LineNumber
, MessageCode
, Text
, MsgFmt
, List
);
334 Print a Debug message.
337 FileName - typically the name of the utility printing the debug message, but
338 can be the name of a file being parsed.
340 LineNumber - the line number in FileName (parsers)
342 MsgLevel - Debug message print level (0~9)
344 Text - the text in question (parsers)
346 MsgFmt - the format string for the debug message. Can contain formatting
347 controls for use with varargs.
356 // If the debug level is less than current print level, then do nothing.
358 if (MsgLevel
< mPrintLogLevel
) {
362 va_start (List
, MsgFmt
);
363 PrintMessage ("DEBUG", FileName
, LineNumber
, 0, Text
, MsgFmt
, List
);
380 Worker routine for all the utility printing services. Prints the message in
381 a format that Visual Studio will find when scanning build outputs for
385 Type - "warning" or "error" string to insert into the message to be
386 printed. The first character of this string (converted to uppercase)
387 is used to preceed the MessageCode value in the output string.
389 FileName - name of the file where the warning was detected, or the name
390 of the application that detected the warning
392 LineNumber - the line number where the warning was detected (parsers).
393 0 should be specified if the utility is not a parser.
395 MessageCode - an application-specific warning code that can be referenced in
398 Text - part of the message to print
400 MsgFmt - the format string for the message. Can contain formatting
401 controls for use with varargs.
402 List - the variable list.
408 If FileName == NULL then this utility will use the string passed into SetUtilityName().
410 LineNumber is only used if the caller is a parser, in which case FileName refers to the
413 Text and MsgFmt are both optional, though it would be of little use calling this function with
416 Output will typically be of the form:
417 <FileName>(<LineNumber>) : <Type> <Type[0]><MessageCode>: <Text> : <MsgFmt>
419 Parser (LineNumber != 0)
420 VfrCompile.cpp(330) : error E2660: AddVfrDataStructField : function does not take 2 parameters
421 Generic utility (LineNumber == 0)
422 UtilityName : error E1234 : Text string : MsgFmt string and args
426 CHAR8 Line
[MAX_LINE_LEN
];
427 CHAR8 Line2
[MAX_LINE_LEN
];
433 // init local variable
439 // If given a filename, then add it (and the line number) to the string.
440 // If there's no filename, then use the program name if provided.
442 if (FileName
!= NULL
) {
448 if (strcmp (Type
, "DEBUG") == 0) {
450 // Debug Message requires current time.
453 NewTime
= localtime (&CurrentTime
);
454 if (NewTime
!= NULL
) {
455 fprintf (stdout
, "%04d-%02d-%02d %02d:%02d:%02d",
456 NewTime
->tm_year
+ 1900,
465 sprintf (Line
, ": %s", Cptr
);
466 if (LineNumber
!= 0) {
467 sprintf (Line2
, "(%u)", (unsigned) LineNumber
);
468 strcat (Line
, Line2
);
473 // Error and Warning Information.
476 if (mUtilityName
[0] != '\0') {
477 fprintf (stdout
, "%s...\n", mUtilityName
);
479 sprintf (Line
, "%s", Cptr
);
480 if (LineNumber
!= 0) {
481 sprintf (Line2
, "(%u)", (unsigned) LineNumber
);
482 strcat (Line
, Line2
);
485 if (mUtilityName
[0] != '\0') {
486 sprintf (Line
, "%s", mUtilityName
);
490 if (strcmp (Type
, "ERROR") == 0) {
492 // Set status accordingly for ERROR information.
494 if (mStatus
< STATUS_ERROR
) {
495 mStatus
= STATUS_ERROR
;
501 // Have to print an error code or Visual Studio won't find the
502 // message for you. It has to be decimal digits too.
504 if (MessageCode
!= 0) {
505 sprintf (Line2
, ": %s %04u", Type
, (unsigned) MessageCode
);
507 sprintf (Line2
, ": %s", Type
);
509 strcat (Line
, Line2
);
510 fprintf (stdout
, "%s", Line
);
512 // If offending text was provided, then print it
515 fprintf (stdout
, ": %s", Text
);
517 fprintf (stdout
, "\n");
520 // Print formatted message if provided
522 if (MsgFmt
!= NULL
) {
523 vsprintf (Line2
, MsgFmt
, List
);
524 fprintf (stdout
, " %s\n", Line2
);
537 Print message into stdout.
540 MsgFmt - the format string for the message. Can contain formatting
541 controls for use with varargs.
542 List - the variable list.
548 CHAR8 Line
[MAX_LINE_LEN
];
550 // Print formatted message if provided
552 if (MsgFmt
!= NULL
) {
553 vsprintf (Line
, MsgFmt
, List
);
554 fprintf (stdout
, "%s\n", Line
);
560 CHAR8
*SourceFileName
,
566 Set the position in a file being parsed. This can be used to
567 print error messages deeper down in a parser.
570 SourceFileName - name of the source file being parsed
571 LineNum - line number of the source file being parsed
578 mSourceFileName
= SourceFileName
;
579 mSourceFileLineNum
= LineNum
;
589 All printed error/warning/debug messages follow the same format, and
590 typically will print a filename or utility name followed by the error
591 text. However if a filename is not passed to the print routines, then
592 they'll print the utility name if you call this function early in your
593 app to set the utility name.
596 UtilityName - name of the utility, which will be printed with all
597 error/warning/debug messags.
605 // Save the name of the utility in our local variable. Make sure its
606 // length does not exceed our buffer.
608 if (UtilityName
!= NULL
) {
609 if (strlen (UtilityName
) >= sizeof (mUtilityName
)) {
610 Error (UtilityName
, 0, 0, "application error", "utility name length exceeds internal buffer size");
611 strncpy (mUtilityName
, UtilityName
, sizeof (mUtilityName
) - 1);
612 mUtilityName
[sizeof (mUtilityName
) - 1] = 0;
615 strcpy (mUtilityName
, UtilityName
);
618 Error (NULL
, 0, 0, "application error", "SetUtilityName() called with NULL utility name");
629 When you call Error() or Warning(), this module keeps track of it and
630 sets a local mStatus to STATUS_ERROR or STATUS_WARNING. When the utility
631 exits, it can call this function to get the status and use it as a return
638 Worst-case status reported, as defined by which print function was called.
652 Set the printing message Level. This is used by the PrintMsg() function
653 to determine when/if a message should be printed.
656 LogLevel - 0~50 to specify the different level message.
663 mPrintLogLevel
= LogLevel
;
674 Print a verbose level message.
677 MsgFmt - the format string for the message. Can contain formatting
678 controls for use with varargs.
679 List - the variable list.
688 // If the debug level is less than current print level, then do nothing.
690 if (VERBOSE_LOG_LEVEL
< mPrintLogLevel
) {
694 va_start (List
, MsgFmt
);
695 PrintSimpleMessage (MsgFmt
, List
);
707 Print a default level message.
710 MsgFmt - the format string for the message. Can contain formatting
711 controls for use with varargs.
712 List - the variable list.
721 // If the debug level is less than current print level, then do nothing.
723 if (INFO_LOG_LEVEL
< mPrintLogLevel
) {
727 va_start (List
, MsgFmt
);
728 PrintSimpleMessage (MsgFmt
, List
);
740 Print a key level message.
743 MsgFmt - the format string for the message. Can contain formatting
744 controls for use with varargs.
745 List - the variable list.
754 // If the debug level is less than current print level, then do nothing.
756 if (KEY_LOG_LEVEL
< mPrintLogLevel
) {
760 va_start (List
, MsgFmt
);
761 PrintSimpleMessage (MsgFmt
, List
);
769 UINT32 MaxWarningsPlusErrors
774 Set the limits of how many errors, warnings, and errors+warnings
778 MaxErrors - maximum number of error messages to print
779 MaxWarnings - maximum number of warning messages to print
780 MaxWarningsPlusErrors
781 - maximum number of errors+warnings to print
788 mMaxErrors
= MaxErrors
;
789 mMaxWarnings
= MaxWarnings
;
790 mMaxWarningsPlusErrors
= MaxWarningsPlusErrors
;
800 STATIC INT8 mPrintLimitExceeded
= 0;
802 // If we've already printed the message, do nothing. Otherwise
803 // temporarily increase our print limits so we can pass one
804 // more message through.
806 if (mPrintLimitExceeded
== 0) {
807 mPrintLimitExceeded
++;
810 mMaxWarningsPlusErrors
++;
811 Error (NULL
, 0, 0, "error/warning print limit exceeded", NULL
);
814 mMaxWarningsPlusErrors
--;
820 TestUtilityMessages (
824 CHAR8
*ArgStr
= "ArgString";
829 // Test without setting utility name
831 fprintf (stdout
, "* Testing without setting utility name\n");
832 fprintf (stdout
, "** Test debug message not printed\n");
833 DebugMsg (NULL
, 0, 0x00000001, NULL
, NULL
);
834 fprintf (stdout
, "** Test warning with two strings and two args\n");
835 Warning (NULL
, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
836 fprintf (stdout
, "** Test error with two strings and two args\n");
837 Warning (NULL
, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
838 fprintf (stdout
, "** Test parser warning with nothing\n");
839 ParserWarning (0, NULL
, NULL
);
840 fprintf (stdout
, "** Test parser error with nothing\n");
841 ParserError (0, NULL
, NULL
);
843 // Test with utility name set now
845 fprintf (stdout
, "** Testingin with utility name set\n");
846 SetUtilityName ("MyUtilityName");
851 fprintf (stdout
, "** Test debug message with one string\n");
852 DebugMsg (NULL
, 0, 0x00000002, "Text1", NULL
);
853 fprintf (stdout
, "** Test debug message with one string\n");
854 DebugMsg (NULL
, 0, 0x00000002, NULL
, "Text2");
855 fprintf (stdout
, "** Test debug message with two strings\n");
856 DebugMsg (NULL
, 0, 0x00000002, "Text1", "Text2");
857 fprintf (stdout
, "** Test debug message with two strings and two args\n");
858 DebugMsg (NULL
, 0, 0x00000002, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
860 // Test warning prints
862 fprintf (stdout
, "** Test warning with no strings\n");
863 Warning (NULL
, 0, 1234, NULL
, NULL
);
864 fprintf (stdout
, "** Test warning with one string\n");
865 Warning (NULL
, 0, 1234, "Text1", NULL
);
866 fprintf (stdout
, "** Test warning with one string\n");
867 Warning (NULL
, 0, 1234, NULL
, "Text2");
868 fprintf (stdout
, "** Test warning with two strings and two args\n");
869 Warning (NULL
, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
873 fprintf (stdout
, "** Test error with no strings\n");
874 Error (NULL
, 0, 1234, NULL
, NULL
);
875 fprintf (stdout
, "** Test error with one string\n");
876 Error (NULL
, 0, 1234, "Text1", NULL
);
877 fprintf (stdout
, "** Test error with one string\n");
878 Error (NULL
, 0, 1234, NULL
, "Text2");
879 fprintf (stdout
, "** Test error with two strings and two args\n");
880 Error (NULL
, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
882 // Test parser prints
884 fprintf (stdout
, "** Test parser errors\n");
885 ParserSetPosition (__FILE__
, __LINE__
+ 1);
886 ParserError (1234, NULL
, NULL
);
887 ParserSetPosition (__FILE__
, __LINE__
+ 1);
888 ParserError (1234, "Text1", NULL
);
889 ParserSetPosition (__FILE__
, __LINE__
+ 1);
890 ParserError (1234, NULL
, "Text2");
891 ParserSetPosition (__FILE__
, __LINE__
+ 1);
892 ParserError (1234, "Text1", "Text2");
893 ParserSetPosition (__FILE__
, __LINE__
+ 1);
894 ParserError (1234, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
896 fprintf (stdout
, "** Test parser warnings\n");
897 ParserSetPosition (__FILE__
, __LINE__
+ 1);
898 ParserWarning (4321, NULL
, NULL
);
899 ParserSetPosition (__FILE__
, __LINE__
+ 1);
900 ParserWarning (4321, "Text1", NULL
);
901 ParserSetPosition (__FILE__
, __LINE__
+ 1);
902 ParserWarning (4321, NULL
, "Text2");
903 ParserSetPosition (__FILE__
, __LINE__
+ 1);
904 ParserWarning (4321, "Text1", "Text2");
905 ParserSetPosition (__FILE__
, __LINE__
+ 1);
906 ParserWarning (4321, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);