3 Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.<BR>
4 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;
65 Prints an error message.
68 All arguments are optional, though the printed message may be useless if
69 at least something valid is not specified.
71 FileName - name of the file or application. If not specified, then the
72 utilty name (as set by the utility calling SetUtilityName()
73 earlier) is used. Otherwise "Unknown utility" is used.
75 LineNumber - the line number of error, typically used by parsers. If the
76 utility is not a parser, then 0 should be specified. Otherwise
77 the FileName and LineNumber info can be used to cause
78 MS Visual Studio to jump to the error.
80 MessageCode - an application-specific error code that can be referenced in
83 Text - the text in question, typically used by parsers.
85 MsgFmt - the format string for the error message. Can contain formatting
86 controls for use with the varargs.
92 We print the following (similar to the Warn() and Debug()
94 Typical error/warning message format:
96 bin\VfrCompile.cpp(330) : error C2660: 'AddVfrDataStructField' : function does not take 2 parameters
98 BUGBUG -- these three utility functions are almost identical, and
99 should be modified to share code.
101 Visual Studio does not find error messages with:
115 // If limits have been set, then check that we have not exceeded them
117 if (mPrintLimitsSet
) {
119 // See if we've exceeded our total count
121 if (mMaxWarningsPlusErrors
!= 0) {
122 if (mErrorCount
+ mWarningCount
> mMaxWarningsPlusErrors
) {
123 PrintLimitExceeded ();
128 // See if we've exceeded our error count
130 if (mMaxErrors
!= 0) {
131 if (mErrorCount
> mMaxErrors
) {
132 PrintLimitExceeded ();
139 va_start (List
, MsgFmt
);
140 PrintMessage ("ERROR", FileName
, LineNumber
, MessageCode
, Text
, MsgFmt
, List
);
154 Print a parser error, using the source file name and line number
155 set by a previous call to SetParserPosition().
158 MessageCode - application-specific error code
159 Text - text to print in the error message
160 MsgFmt - format string to print at the end of the error message
169 // If limits have been set, then check them
171 if (mPrintLimitsSet
) {
173 // See if we've exceeded our total count
175 if (mMaxWarningsPlusErrors
!= 0) {
176 if (mErrorCount
+ mWarningCount
> mMaxWarningsPlusErrors
) {
177 PrintLimitExceeded ();
182 // See if we've exceeded our error count
184 if (mMaxErrors
!= 0) {
185 if (mErrorCount
> mMaxErrors
) {
186 PrintLimitExceeded ();
193 va_start (List
, MsgFmt
);
194 PrintMessage ("ERROR", mSourceFileName
, mSourceFileLineNum
, MessageCode
, Text
, MsgFmt
, List
);
201 CHAR8
*OffendingText
,
208 Print a parser warning, using the source file name and line number
209 set by a previous call to SetParserPosition().
212 ErrorCode - application-specific error code
213 OffendingText - text to print in the warning message
214 MsgFmt - format string to print at the end of the warning message
223 // If limits have been set, then check them
225 if (mPrintLimitsSet
) {
227 // See if we've exceeded our total count
229 if (mMaxWarningsPlusErrors
!= 0) {
230 if (mErrorCount
+ mWarningCount
> mMaxWarningsPlusErrors
) {
231 PrintLimitExceeded ();
236 // See if we've exceeded our warning count
238 if (mMaxWarnings
!= 0) {
239 if (mWarningCount
> mMaxWarnings
) {
240 PrintLimitExceeded ();
247 va_start (List
, MsgFmt
);
248 PrintMessage ("WARNING", mSourceFileName
, mSourceFileLineNum
, ErrorCode
, OffendingText
, MsgFmt
, List
);
251 // Don't set warning status accordingly
253 // if (mStatus < STATUS_WARNING) {
254 // mStatus = STATUS_WARNING;
270 Print a warning message.
273 FileName - name of the file where the warning was detected, or the name
274 of the application that detected the warning
276 LineNumber - the line number where the warning was detected (parsers).
277 0 should be specified if the utility is not a parser.
279 MessageCode - an application-specific warning code that can be referenced in
282 Text - the text in question (parsers)
284 MsgFmt - the format string for the warning message. Can contain formatting
285 controls for use with varargs.
295 // Current Print Level not output warning information.
297 if (WARNING_LOG_LEVEL
< mPrintLogLevel
) {
301 // If limits have been set, then check them
303 if (mPrintLimitsSet
) {
305 // See if we've exceeded our total count
307 if (mMaxWarningsPlusErrors
!= 0) {
308 if (mErrorCount
+ mWarningCount
> mMaxWarningsPlusErrors
) {
309 PrintLimitExceeded ();
314 // See if we've exceeded our warning count
316 if (mMaxWarnings
!= 0) {
317 if (mWarningCount
> mMaxWarnings
) {
318 PrintLimitExceeded ();
325 va_start (List
, MsgFmt
);
326 PrintMessage ("WARNING", FileName
, LineNumber
, MessageCode
, Text
, MsgFmt
, List
);
342 Print a Debug message.
345 FileName - typically the name of the utility printing the debug message, but
346 can be the name of a file being parsed.
348 LineNumber - the line number in FileName (parsers)
350 MsgLevel - Debug message print level (0~9)
352 Text - the text in question (parsers)
354 MsgFmt - the format string for the debug message. Can contain formatting
355 controls for use with varargs.
364 // If the debug level is less than current print level, then do nothing.
366 if (MsgLevel
< mPrintLogLevel
) {
370 va_start (List
, MsgFmt
);
371 PrintMessage ("DEBUG", FileName
, LineNumber
, 0, Text
, MsgFmt
, List
);
388 Worker routine for all the utility printing services. Prints the message in
389 a format that Visual Studio will find when scanning build outputs for
393 Type - "warning" or "error" string to insert into the message to be
394 printed. The first character of this string (converted to uppercase)
395 is used to preceed the MessageCode value in the output string.
397 FileName - name of the file where the warning was detected, or the name
398 of the application that detected the warning
400 LineNumber - the line number where the warning was detected (parsers).
401 0 should be specified if the utility is not a parser.
403 MessageCode - an application-specific warning code that can be referenced in
406 Text - part of the message to print
408 MsgFmt - the format string for the message. Can contain formatting
409 controls for use with varargs.
410 List - the variable list.
416 If FileName == NULL then this utility will use the string passed into SetUtilityName().
418 LineNumber is only used if the caller is a parser, in which case FileName refers to the
421 Text and MsgFmt are both optional, though it would be of little use calling this function with
424 Output will typically be of the form:
425 <FileName>(<LineNumber>) : <Type> <Type[0]><MessageCode>: <Text> : <MsgFmt>
427 Parser (LineNumber != 0)
428 VfrCompile.cpp(330) : error E2660: AddVfrDataStructField : function does not take 2 parameters
429 Generic utility (LineNumber == 0)
430 UtilityName : error E1234 : Text string : MsgFmt string and args
434 CHAR8 Line
[MAX_LINE_LEN
];
435 CHAR8 Line2
[MAX_LINE_LEN
];
441 // init local variable
447 // If given a filename, then add it (and the line number) to the string.
448 // If there's no filename, then use the program name if provided.
450 if (FileName
!= NULL
) {
456 if (strcmp (Type
, "DEBUG") == 0) {
458 // Debug Message requires current time.
461 NewTime
= localtime (&CurrentTime
);
462 fprintf (stdout
, "%04d-%02d-%02d %02d:%02d:%02d",
463 NewTime
->tm_year
+ 1900,
471 sprintf (Line
, ": %s", Cptr
);
472 if (LineNumber
!= 0) {
473 sprintf (Line2
, "(%u)", (unsigned) LineNumber
);
474 strcat (Line
, Line2
);
479 // Error and Warning Information.
482 if (mUtilityName
[0] != '\0') {
483 fprintf (stdout
, "%s...\n", mUtilityName
);
485 sprintf (Line
, "%s", Cptr
);
486 if (LineNumber
!= 0) {
487 sprintf (Line2
, "(%u)", (unsigned) LineNumber
);
488 strcat (Line
, Line2
);
491 if (mUtilityName
[0] != '\0') {
492 sprintf (Line
, "%s", mUtilityName
);
496 if (strcmp (Type
, "ERROR") == 0) {
498 // Set status accordingly for ERROR information.
500 if (mStatus
< STATUS_ERROR
) {
501 mStatus
= STATUS_ERROR
;
507 // Have to print an error code or Visual Studio won't find the
508 // message for you. It has to be decimal digits too.
510 if (MessageCode
!= 0) {
511 sprintf (Line2
, ": %s %04u", Type
, (unsigned) MessageCode
);
513 sprintf (Line2
, ": %s", Type
);
515 strcat (Line
, Line2
);
516 fprintf (stdout
, "%s", Line
);
518 // If offending text was provided, then print it
521 fprintf (stdout
, ": %s", Text
);
523 fprintf (stdout
, "\n");
526 // Print formatted message if provided
528 if (MsgFmt
!= NULL
) {
529 vsprintf (Line2
, MsgFmt
, List
);
530 fprintf (stdout
, " %s\n", Line2
);
543 Print message into stdout.
546 MsgFmt - the format string for the message. Can contain formatting
547 controls for use with varargs.
548 List - the variable list.
554 CHAR8 Line
[MAX_LINE_LEN
];
556 // Print formatted message if provided
558 if (MsgFmt
!= NULL
) {
559 vsprintf (Line
, MsgFmt
, List
);
560 fprintf (stdout
, "%s\n", Line
);
566 CHAR8
*SourceFileName
,
572 Set the position in a file being parsed. This can be used to
573 print error messages deeper down in a parser.
576 SourceFileName - name of the source file being parsed
577 LineNum - line number of the source file being parsed
584 mSourceFileName
= SourceFileName
;
585 mSourceFileLineNum
= LineNum
;
595 All printed error/warning/debug messages follow the same format, and
596 typically will print a filename or utility name followed by the error
597 text. However if a filename is not passed to the print routines, then
598 they'll print the utility name if you call this function early in your
599 app to set the utility name.
602 UtilityName - name of the utility, which will be printed with all
603 error/warning/debug messags.
611 // Save the name of the utility in our local variable. Make sure its
612 // length does not exceed our buffer.
614 if (UtilityName
!= NULL
) {
615 if (strlen (UtilityName
) >= sizeof (mUtilityName
)) {
616 Error (UtilityName
, 0, 0, "application error", "utility name length exceeds internal buffer size");
617 strncpy (mUtilityName
, UtilityName
, sizeof (mUtilityName
) - 1);
618 mUtilityName
[sizeof (mUtilityName
) - 1] = 0;
621 strcpy (mUtilityName
, UtilityName
);
624 Error (NULL
, 0, 0, "application error", "SetUtilityName() called with NULL utility name");
635 When you call Error() or Warning(), this module keeps track of it and
636 sets a local mStatus to STATUS_ERROR or STATUS_WARNING. When the utility
637 exits, it can call this function to get the status and use it as a return
644 Worst-case status reported, as defined by which print function was called.
658 Set the printing message Level. This is used by the PrintMsg() function
659 to determine when/if a message should be printed.
662 LogLevel - 0~50 to specify the different level message.
669 mPrintLogLevel
= LogLevel
;
680 Print a verbose level message.
683 MsgFmt - the format string for the message. Can contain formatting
684 controls for use with varargs.
685 List - the variable list.
694 // If the debug level is less than current print level, then do nothing.
696 if (VERBOSE_LOG_LEVEL
< mPrintLogLevel
) {
700 va_start (List
, MsgFmt
);
701 PrintSimpleMessage (MsgFmt
, List
);
713 Print a default level message.
716 MsgFmt - the format string for the message. Can contain formatting
717 controls for use with varargs.
718 List - the variable list.
727 // If the debug level is less than current print level, then do nothing.
729 if (INFO_LOG_LEVEL
< mPrintLogLevel
) {
733 va_start (List
, MsgFmt
);
734 PrintSimpleMessage (MsgFmt
, List
);
746 Print a key level message.
749 MsgFmt - the format string for the message. Can contain formatting
750 controls for use with varargs.
751 List - the variable list.
760 // If the debug level is less than current print level, then do nothing.
762 if (KEY_LOG_LEVEL
< mPrintLogLevel
) {
766 va_start (List
, MsgFmt
);
767 PrintSimpleMessage (MsgFmt
, List
);
775 UINT32 MaxWarningsPlusErrors
780 Set the limits of how many errors, warnings, and errors+warnings
784 MaxErrors - maximum number of error messages to print
785 MaxWarnings - maximum number of warning messages to print
786 MaxWarningsPlusErrors
787 - maximum number of errors+warnings to print
794 mMaxErrors
= MaxErrors
;
795 mMaxWarnings
= MaxWarnings
;
796 mMaxWarningsPlusErrors
= MaxWarningsPlusErrors
;
806 STATIC INT8 mPrintLimitExceeded
= 0;
808 // If we've already printed the message, do nothing. Otherwise
809 // temporarily increase our print limits so we can pass one
810 // more message through.
812 if (mPrintLimitExceeded
== 0) {
813 mPrintLimitExceeded
++;
816 mMaxWarningsPlusErrors
++;
817 Error (NULL
, 0, 0, "error/warning print limit exceeded", NULL
);
820 mMaxWarningsPlusErrors
--;
826 TestUtilityMessages (
830 CHAR8
*ArgStr
= "ArgString";
835 // Test without setting utility name
837 fprintf (stdout
, "* Testing without setting utility name\n");
838 fprintf (stdout
, "** Test debug message not printed\n");
839 DebugMsg (NULL
, 0, 0x00000001, NULL
, NULL
);
840 fprintf (stdout
, "** Test warning with two strings and two args\n");
841 Warning (NULL
, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
842 fprintf (stdout
, "** Test error with two strings and two args\n");
843 Warning (NULL
, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
844 fprintf (stdout
, "** Test parser warning with nothing\n");
845 ParserWarning (0, NULL
, NULL
);
846 fprintf (stdout
, "** Test parser error with nothing\n");
847 ParserError (0, NULL
, NULL
);
849 // Test with utility name set now
851 fprintf (stdout
, "** Testingin with utility name set\n");
852 SetUtilityName ("MyUtilityName");
857 fprintf (stdout
, "** Test debug message with one string\n");
858 DebugMsg (NULL
, 0, 0x00000002, "Text1", NULL
);
859 fprintf (stdout
, "** Test debug message with one string\n");
860 DebugMsg (NULL
, 0, 0x00000002, NULL
, "Text2");
861 fprintf (stdout
, "** Test debug message with two strings\n");
862 DebugMsg (NULL
, 0, 0x00000002, "Text1", "Text2");
863 fprintf (stdout
, "** Test debug message with two strings and two args\n");
864 DebugMsg (NULL
, 0, 0x00000002, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
866 // Test warning prints
868 fprintf (stdout
, "** Test warning with no strings\n");
869 Warning (NULL
, 0, 1234, NULL
, NULL
);
870 fprintf (stdout
, "** Test warning with one string\n");
871 Warning (NULL
, 0, 1234, "Text1", NULL
);
872 fprintf (stdout
, "** Test warning with one string\n");
873 Warning (NULL
, 0, 1234, NULL
, "Text2");
874 fprintf (stdout
, "** Test warning with two strings and two args\n");
875 Warning (NULL
, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
879 fprintf (stdout
, "** Test error with no strings\n");
880 Error (NULL
, 0, 1234, NULL
, NULL
);
881 fprintf (stdout
, "** Test error with one string\n");
882 Error (NULL
, 0, 1234, "Text1", NULL
);
883 fprintf (stdout
, "** Test error with one string\n");
884 Error (NULL
, 0, 1234, NULL
, "Text2");
885 fprintf (stdout
, "** Test error with two strings and two args\n");
886 Error (NULL
, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
888 // Test parser prints
890 fprintf (stdout
, "** Test parser errors\n");
891 ParserSetPosition (__FILE__
, __LINE__
+ 1);
892 ParserError (1234, NULL
, NULL
);
893 ParserSetPosition (__FILE__
, __LINE__
+ 1);
894 ParserError (1234, "Text1", NULL
);
895 ParserSetPosition (__FILE__
, __LINE__
+ 1);
896 ParserError (1234, NULL
, "Text2");
897 ParserSetPosition (__FILE__
, __LINE__
+ 1);
898 ParserError (1234, "Text1", "Text2");
899 ParserSetPosition (__FILE__
, __LINE__
+ 1);
900 ParserError (1234, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
902 fprintf (stdout
, "** Test parser warnings\n");
903 ParserSetPosition (__FILE__
, __LINE__
+ 1);
904 ParserWarning (4321, NULL
, NULL
);
905 ParserSetPosition (__FILE__
, __LINE__
+ 1);
906 ParserWarning (4321, "Text1", NULL
);
907 ParserSetPosition (__FILE__
, __LINE__
+ 1);
908 ParserWarning (4321, NULL
, "Text2");
909 ParserSetPosition (__FILE__
, __LINE__
+ 1);
910 ParserWarning (4321, "Text1", "Text2");
911 ParserSetPosition (__FILE__
, __LINE__
+ 1);
912 ParserWarning (4321, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);