3 Copyright (c) 2004 - 2008, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 EFI tools utility functions to display warning, error, and informational
29 #include "EfiUtilityMsgs.h"
32 // Declare module globals for keeping track of the the utility's
33 // name and other settings.
35 STATIC STATUS mStatus
= STATUS_SUCCESS
;
36 STATIC CHAR8 mUtilityName
[50] = { 0 };
37 STATIC UINT64 mPrintLogLevel
= INFO_LOG_LEVEL
;
38 STATIC CHAR8
*mSourceFileName
= NULL
;
39 STATIC UINT32 mSourceFileLineNum
= 0;
40 STATIC UINT32 mErrorCount
= 0;
41 STATIC UINT32 mWarningCount
= 0;
42 STATIC UINT32 mMaxErrors
= 0;
43 STATIC UINT32 mMaxWarnings
= 0;
44 STATIC UINT32 mMaxWarningsPlusErrors
= 0;
45 STATIC INT8 mPrintLimitsSet
= 0;
77 Prints an error message.
80 All arguments are optional, though the printed message may be useless if
81 at least something valid is not specified.
83 FileName - name of the file or application. If not specified, then the
84 utilty name (as set by the utility calling SetUtilityName()
85 earlier) is used. Otherwise "Unknown utility" is used.
87 LineNumber - the line number of error, typically used by parsers. If the
88 utility is not a parser, then 0 should be specified. Otherwise
89 the FileName and LineNumber info can be used to cause
90 MS Visual Studio to jump to the error.
92 MessageCode - an application-specific error code that can be referenced in
95 Text - the text in question, typically used by parsers.
97 MsgFmt - the format string for the error message. Can contain formatting
98 controls for use with the varargs.
104 We print the following (similar to the Warn() and Debug()
106 Typical error/warning message format:
108 bin\VfrCompile.cpp(330) : error C2660: 'AddVfrDataStructField' : function does not take 2 parameters
110 BUGBUG -- these three utility functions are almost identical, and
111 should be modified to share code.
113 Visual Studio does not find error messages with:
127 // If limits have been set, then check that we have not exceeded them
129 if (mPrintLimitsSet
) {
131 // See if we've exceeded our total count
133 if (mMaxWarningsPlusErrors
!= 0) {
134 if (mErrorCount
+ mWarningCount
> mMaxWarningsPlusErrors
) {
135 PrintLimitExceeded ();
140 // See if we've exceeded our error count
142 if (mMaxErrors
!= 0) {
143 if (mErrorCount
> mMaxErrors
) {
144 PrintLimitExceeded ();
151 va_start (List
, MsgFmt
);
152 PrintMessage ("ERROR", FileName
, LineNumber
, MessageCode
, Text
, MsgFmt
, List
);
155 // Set status accordingly
157 if (mStatus
< STATUS_ERROR
) {
158 mStatus
= STATUS_ERROR
;
172 Print a parser error, using the source file name and line number
173 set by a previous call to SetParserPosition().
176 MessageCode - application-specific error code
177 Text - text to print in the error message
178 MsgFmt - format string to print at the end of the error message
187 // If limits have been set, then check them
189 if (mPrintLimitsSet
) {
191 // See if we've exceeded our total count
193 if (mMaxWarningsPlusErrors
!= 0) {
194 if (mErrorCount
+ mWarningCount
> mMaxWarningsPlusErrors
) {
195 PrintLimitExceeded ();
200 // See if we've exceeded our error count
202 if (mMaxErrors
!= 0) {
203 if (mErrorCount
> mMaxErrors
) {
204 PrintLimitExceeded ();
211 va_start (List
, MsgFmt
);
212 PrintMessage ("ERROR", mSourceFileName
, mSourceFileLineNum
, MessageCode
, Text
, MsgFmt
, List
);
215 // Set status accordingly
217 if (mStatus
< STATUS_ERROR
) {
218 mStatus
= STATUS_ERROR
;
225 CHAR8
*OffendingText
,
232 Print a parser warning, using the source file name and line number
233 set by a previous call to SetParserPosition().
236 ErrorCode - application-specific error code
237 OffendingText - text to print in the warning message
238 MsgFmt - format string to print at the end of the warning message
247 // If limits have been set, then check them
249 if (mPrintLimitsSet
) {
251 // See if we've exceeded our total count
253 if (mMaxWarningsPlusErrors
!= 0) {
254 if (mErrorCount
+ mWarningCount
> mMaxWarningsPlusErrors
) {
255 PrintLimitExceeded ();
260 // See if we've exceeded our warning count
262 if (mMaxWarnings
!= 0) {
263 if (mWarningCount
> mMaxWarnings
) {
264 PrintLimitExceeded ();
271 va_start (List
, MsgFmt
);
272 PrintMessage ("WARNING", mSourceFileName
, mSourceFileLineNum
, ErrorCode
, OffendingText
, MsgFmt
, List
);
275 // Don't set warning status accordingly
277 // if (mStatus < STATUS_WARNING) {
278 // mStatus = STATUS_WARNING;
294 Print a warning message.
297 FileName - name of the file where the warning was detected, or the name
298 of the application that detected the warning
300 LineNumber - the line number where the warning was detected (parsers).
301 0 should be specified if the utility is not a parser.
303 MessageCode - an application-specific warning code that can be referenced in
306 Text - the text in question (parsers)
308 MsgFmt - the format string for the warning message. Can contain formatting
309 controls for use with varargs.
319 // Current Print Level not output warning information.
321 if (WARNING_LOG_LEVEL
< mPrintLogLevel
) {
325 // If limits have been set, then check them
327 if (mPrintLimitsSet
) {
329 // See if we've exceeded our total count
331 if (mMaxWarningsPlusErrors
!= 0) {
332 if (mErrorCount
+ mWarningCount
> mMaxWarningsPlusErrors
) {
333 PrintLimitExceeded ();
338 // See if we've exceeded our warning count
340 if (mMaxWarnings
!= 0) {
341 if (mWarningCount
> mMaxWarnings
) {
342 PrintLimitExceeded ();
349 va_start (List
, MsgFmt
);
350 PrintMessage ("WARNING", FileName
, LineNumber
, MessageCode
, Text
, MsgFmt
, List
);
366 Print a Debug message.
369 FileName - typically the name of the utility printing the debug message, but
370 can be the name of a file being parsed.
372 LineNumber - the line number in FileName (parsers)
374 MsgLevel - Debug message print level (0~9)
376 Text - the text in question (parsers)
378 MsgFmt - the format string for the debug message. Can contain formatting
379 controls for use with varargs.
388 // If the debug level is less than current print level, then do nothing.
390 if (MsgLevel
< mPrintLogLevel
) {
394 va_start (List
, MsgFmt
);
395 PrintMessage ("DEBUG", FileName
, LineNumber
, 0, Text
, MsgFmt
, List
);
413 Worker routine for all the utility printing services. Prints the message in
414 a format that Visual Studio will find when scanning build outputs for
418 Type - "warning" or "error" string to insert into the message to be
419 printed. The first character of this string (converted to uppercase)
420 is used to preceed the MessageCode value in the output string.
422 FileName - name of the file where the warning was detected, or the name
423 of the application that detected the warning
425 LineNumber - the line number where the warning was detected (parsers).
426 0 should be specified if the utility is not a parser.
428 MessageCode - an application-specific warning code that can be referenced in
431 Text - part of the message to print
433 MsgFmt - the format string for the message. Can contain formatting
434 controls for use with varargs.
435 List - the variable list.
441 If FileName == NULL then this utility will use the string passed into SetUtilityName().
443 LineNumber is only used if the caller is a parser, in which case FileName refers to the
446 Text and MsgFmt are both optional, though it would be of little use calling this function with
449 Output will typically be of the form:
450 <FileName>(<LineNumber>) : <Type> <Type[0]><MessageCode>: <Text> : <MsgFmt>
452 Parser (LineNumber != 0)
453 VfrCompile.cpp(330) : error E2660: AddVfrDataStructField : function does not take 2 parameters
454 Generic utility (LineNumber == 0)
455 UtilityName : error E1234 : Text string : MsgFmt string and args
459 CHAR8 Line
[MAX_LINE_LEN
];
460 CHAR8 Line2
[MAX_LINE_LEN
];
466 // init local variable
472 // If given a filename, then add it (and the line number) to the string.
473 // If there's no filename, then use the program name if provided.
475 if (FileName
!= NULL
) {
481 if (strcmp (Type
, "DEBUG") == 0) {
483 // Debug Message requires current time.
486 NewTime
= localtime (&CurrentTime
);
487 fprintf (stdout
, "%04d-%02d-%02d %02d:%02d:%02d",
488 NewTime
->tm_year
+ 1900,
496 sprintf (Line
, ": %s", Cptr
);
497 if (LineNumber
!= 0) {
498 sprintf (Line2
, "(%u)", (unsigned) LineNumber
);
499 strcat (Line
, Line2
);
504 // Error and Warning Information.
507 if (mUtilityName
[0] != '\0') {
508 fprintf (stdout
, "%s...\n", mUtilityName
);
510 sprintf (Line
, "%s", Cptr
);
511 if (LineNumber
!= 0) {
512 sprintf (Line2
, "(%u)", (unsigned) LineNumber
);
513 strcat (Line
, Line2
);
516 if (mUtilityName
[0] != '\0') {
517 sprintf (Line
, "%s", mUtilityName
);
523 // Have to print an error code or Visual Studio won't find the
524 // message for you. It has to be decimal digits too.
526 if (MessageCode
!= 0) {
527 sprintf (Line2
, ": %s %04u", Type
, (unsigned) MessageCode
);
529 sprintf (Line2
, ": %s", Type
);
531 strcat (Line
, Line2
);
532 fprintf (stdout
, "%s", Line
);
534 // If offending text was provided, then print it
537 fprintf (stdout
, ": %s", Text
);
539 fprintf (stdout
, "\n");
542 // Print formatted message if provided
544 if (MsgFmt
!= NULL
) {
545 vsprintf (Line2
, MsgFmt
, List
);
546 fprintf (stdout
, " %s\n", Line2
);
558 Print message into stdout.
561 MsgFmt - the format string for the message. Can contain formatting
562 controls for use with varargs.
563 List - the variable list.
569 CHAR8 Line
[MAX_LINE_LEN
];
571 // Print formatted message if provided
573 if (MsgFmt
!= NULL
) {
574 vsprintf (Line
, MsgFmt
, List
);
575 fprintf (stdout
, "%s\n", Line
);
581 CHAR8
*SourceFileName
,
587 Set the position in a file being parsed. This can be used to
588 print error messages deeper down in a parser.
591 SourceFileName - name of the source file being parsed
592 LineNum - line number of the source file being parsed
599 mSourceFileName
= SourceFileName
;
600 mSourceFileLineNum
= LineNum
;
610 All printed error/warning/debug messages follow the same format, and
611 typically will print a filename or utility name followed by the error
612 text. However if a filename is not passed to the print routines, then
613 they'll print the utility name if you call this function early in your
614 app to set the utility name.
617 UtilityName - name of the utility, which will be printed with all
618 error/warning/debug messags.
626 // Save the name of the utility in our local variable. Make sure its
627 // length does not exceed our buffer.
629 if (UtilityName
!= NULL
) {
630 if (strlen (UtilityName
) >= sizeof (mUtilityName
)) {
631 Error (UtilityName
, 0, 0, "application error", "utility name length exceeds internal buffer size");
632 strncpy (mUtilityName
, UtilityName
, sizeof (mUtilityName
) - 1);
633 mUtilityName
[sizeof (mUtilityName
) - 1] = 0;
636 strcpy (mUtilityName
, UtilityName
);
639 Error (NULL
, 0, 0, "application error", "SetUtilityName() called with NULL utility name");
650 When you call Error() or Warning(), this module keeps track of it and
651 sets a local mStatus to STATUS_ERROR or STATUS_WARNING. When the utility
652 exits, it can call this function to get the status and use it as a return
659 Worst-case status reported, as defined by which print function was called.
673 Set the printing message Level. This is used by the PrintMsg() function
674 to determine when/if a message should be printed.
677 LogLevel - 0~50 to specify the different level message.
684 mPrintLogLevel
= LogLevel
;
695 Print a verbose level message.
698 MsgFmt - the format string for the message. Can contain formatting
699 controls for use with varargs.
700 List - the variable list.
709 // If the debug level is less than current print level, then do nothing.
711 if (VERBOSE_LOG_LEVEL
< mPrintLogLevel
) {
715 va_start (List
, MsgFmt
);
716 PrintSimpleMessage (MsgFmt
, List
);
728 Print a default level message.
731 MsgFmt - the format string for the message. Can contain formatting
732 controls for use with varargs.
733 List - the variable list.
742 // If the debug level is less than current print level, then do nothing.
744 if (INFO_LOG_LEVEL
< mPrintLogLevel
) {
748 va_start (List
, MsgFmt
);
749 PrintSimpleMessage (MsgFmt
, List
);
761 Print a key level message.
764 MsgFmt - the format string for the message. Can contain formatting
765 controls for use with varargs.
766 List - the variable list.
775 // If the debug level is less than current print level, then do nothing.
777 if (KEY_LOG_LEVEL
< mPrintLogLevel
) {
781 va_start (List
, MsgFmt
);
782 PrintSimpleMessage (MsgFmt
, List
);
790 UINT32 MaxWarningsPlusErrors
795 Set the limits of how many errors, warnings, and errors+warnings
799 MaxErrors - maximum number of error messages to print
800 MaxWarnings - maximum number of warning messages to print
801 MaxWarningsPlusErrors
802 - maximum number of errors+warnings to print
809 mMaxErrors
= MaxErrors
;
810 mMaxWarnings
= MaxWarnings
;
811 mMaxWarningsPlusErrors
= MaxWarningsPlusErrors
;
821 STATIC INT8 mPrintLimitExceeded
= 0;
823 // If we've already printed the message, do nothing. Otherwise
824 // temporarily increase our print limits so we can pass one
825 // more message through.
827 if (mPrintLimitExceeded
== 0) {
828 mPrintLimitExceeded
++;
831 mMaxWarningsPlusErrors
++;
832 Error (NULL
, 0, 0, "error/warning print limit exceeded", NULL
);
835 mMaxWarningsPlusErrors
--;
841 TestUtilityMessages (
845 CHAR8
*ArgStr
= "ArgString";
850 // Test without setting utility name
852 fprintf (stdout
, "* Testing without setting utility name\n");
853 fprintf (stdout
, "** Test debug message not printed\n");
854 DebugMsg (NULL
, 0, 0x00000001, NULL
, NULL
);
855 fprintf (stdout
, "** Test warning with two strings and two args\n");
856 Warning (NULL
, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
857 fprintf (stdout
, "** Test error with two strings and two args\n");
858 Warning (NULL
, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
859 fprintf (stdout
, "** Test parser warning with nothing\n");
860 ParserWarning (0, NULL
, NULL
);
861 fprintf (stdout
, "** Test parser error with nothing\n");
862 ParserError (0, NULL
, NULL
);
864 // Test with utility name set now
866 fprintf (stdout
, "** Testingin with utility name set\n");
867 SetUtilityName ("MyUtilityName");
872 fprintf (stdout
, "** Test debug message with one string\n");
873 DebugMsg (NULL
, 0, 0x00000002, "Text1", NULL
);
874 fprintf (stdout
, "** Test debug message with one string\n");
875 DebugMsg (NULL
, 0, 0x00000002, NULL
, "Text2");
876 fprintf (stdout
, "** Test debug message with two strings\n");
877 DebugMsg (NULL
, 0, 0x00000002, "Text1", "Text2");
878 fprintf (stdout
, "** Test debug message with two strings and two args\n");
879 DebugMsg (NULL
, 0, 0x00000002, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
881 // Test warning prints
883 fprintf (stdout
, "** Test warning with no strings\n");
884 Warning (NULL
, 0, 1234, NULL
, NULL
);
885 fprintf (stdout
, "** Test warning with one string\n");
886 Warning (NULL
, 0, 1234, "Text1", NULL
);
887 fprintf (stdout
, "** Test warning with one string\n");
888 Warning (NULL
, 0, 1234, NULL
, "Text2");
889 fprintf (stdout
, "** Test warning with two strings and two args\n");
890 Warning (NULL
, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
894 fprintf (stdout
, "** Test error with no strings\n");
895 Error (NULL
, 0, 1234, NULL
, NULL
);
896 fprintf (stdout
, "** Test error with one string\n");
897 Error (NULL
, 0, 1234, "Text1", NULL
);
898 fprintf (stdout
, "** Test error with one string\n");
899 Error (NULL
, 0, 1234, NULL
, "Text2");
900 fprintf (stdout
, "** Test error with two strings and two args\n");
901 Error (NULL
, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
903 // Test parser prints
905 fprintf (stdout
, "** Test parser errors\n");
906 ParserSetPosition (__FILE__
, __LINE__
+ 1);
907 ParserError (1234, NULL
, NULL
);
908 ParserSetPosition (__FILE__
, __LINE__
+ 1);
909 ParserError (1234, "Text1", NULL
);
910 ParserSetPosition (__FILE__
, __LINE__
+ 1);
911 ParserError (1234, NULL
, "Text2");
912 ParserSetPosition (__FILE__
, __LINE__
+ 1);
913 ParserError (1234, "Text1", "Text2");
914 ParserSetPosition (__FILE__
, __LINE__
+ 1);
915 ParserError (1234, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
917 fprintf (stdout
, "** Test parser warnings\n");
918 ParserSetPosition (__FILE__
, __LINE__
+ 1);
919 ParserWarning (4321, NULL
, NULL
);
920 ParserSetPosition (__FILE__
, __LINE__
+ 1);
921 ParserWarning (4321, "Text1", NULL
);
922 ParserSetPosition (__FILE__
, __LINE__
+ 1);
923 ParserWarning (4321, NULL
, "Text2");
924 ParserSetPosition (__FILE__
, __LINE__
+ 1);
925 ParserWarning (4321, "Text1", "Text2");
926 ParserSetPosition (__FILE__
, __LINE__
+ 1);
927 ParserWarning (4321, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);