3 Copyright (c) 2004, 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
28 #include "EfiUtilityMsgs.h"
30 #define MAX_LINE_LEN 200
33 // Declare module globals for keeping track of the the utility's
34 // name and other settings.
36 static STATUS mStatus
= STATUS_SUCCESS
;
37 static CHAR8 mUtilityName
[50] = { 0 };
38 static UINT32 mDebugMsgMask
= 0;
39 static CHAR8
*mSourceFileName
= NULL
;
40 static UINT32 mSourceFileLineNum
= 0;
41 static UINT32 mErrorCount
= 0;
42 static UINT32 mWarningCount
= 0;
43 static UINT32 mMaxErrors
= 0;
44 static UINT32 mMaxWarnings
= 0;
45 static UINT32 mMaxWarningsPlusErrors
= 0;
46 static INT8 mPrintLimitsSet
= 0;
78 Prints an error message.
81 All arguments are optional, though the printed message may be useless if
82 at least something valid is not specified.
84 FileName - name of the file or application. If not specified, then the
85 utilty name (as set by the utility calling SetUtilityName()
86 earlier) is used. Otherwise "Unknown utility" is used.
88 LineNumber - the line number of error, typically used by parsers. If the
89 utility is not a parser, then 0 should be specified. Otherwise
90 the FileName and LineNumber info can be used to cause
91 MS Visual Studio to jump to the error.
93 MessageCode - an application-specific error code that can be referenced in
96 Text - the text in question, typically used by parsers.
98 MsgFmt - the format string for the error message. Can contain formatting
99 controls for use with the varargs.
105 We print the following (similar to the Warn() and Debug()
107 Typical error/warning message format:
109 bin\VfrCompile.cpp(330) : error C2660: 'AddVfrDataStructField' : function does not take 2 parameters
111 BUGBUG -- these three utility functions are almost identical, and
112 should be modified to share code.
114 Visual Studio does not find error messages with:
128 // If limits have been set, then check that we have not exceeded them
130 if (mPrintLimitsSet
) {
132 // See if we've exceeded our total count
134 if (mMaxWarningsPlusErrors
!= 0) {
135 if (mErrorCount
+ mWarningCount
> mMaxWarningsPlusErrors
) {
136 PrintLimitExceeded ();
141 // See if we've exceeded our error count
143 if (mMaxErrors
!= 0) {
144 if (mErrorCount
> mMaxErrors
) {
145 PrintLimitExceeded ();
152 va_start (List
, MsgFmt
);
153 PrintMessage ("error", FileName
, LineNumber
, MessageCode
, Text
, MsgFmt
, List
);
156 // Set status accordingly
158 if (mStatus
< STATUS_ERROR
) {
159 mStatus
= STATUS_ERROR
;
173 Print a parser error, using the source file name and line number
174 set by a previous call to SetParserPosition().
177 MessageCode - application-specific error code
178 Text - text to print in the error message
179 MsgFmt - format string to print at the end of the error message
188 // If limits have been set, then check them
190 if (mPrintLimitsSet
) {
192 // See if we've exceeded our total count
194 if (mMaxWarningsPlusErrors
!= 0) {
195 if (mErrorCount
+ mWarningCount
> mMaxWarningsPlusErrors
) {
196 PrintLimitExceeded ();
201 // See if we've exceeded our error count
203 if (mMaxErrors
!= 0) {
204 if (mErrorCount
> mMaxErrors
) {
205 PrintLimitExceeded ();
212 va_start (List
, MsgFmt
);
213 PrintMessage ("error", mSourceFileName
, mSourceFileLineNum
, MessageCode
, Text
, MsgFmt
, List
);
216 // Set status accordingly
218 if (mStatus
< STATUS_ERROR
) {
219 mStatus
= STATUS_ERROR
;
226 CHAR8
*OffendingText
,
233 Print a parser warning, using the source file name and line number
234 set by a previous call to SetParserPosition().
237 ErrorCode - application-specific error code
238 OffendingText - text to print in the warning message
239 MsgFmt - format string to print at the end of the warning message
248 // If limits have been set, then check them
250 if (mPrintLimitsSet
) {
252 // See if we've exceeded our total count
254 if (mMaxWarningsPlusErrors
!= 0) {
255 if (mErrorCount
+ mWarningCount
> mMaxWarningsPlusErrors
) {
256 PrintLimitExceeded ();
261 // See if we've exceeded our warning count
263 if (mMaxWarnings
!= 0) {
264 if (mWarningCount
> mMaxWarnings
) {
265 PrintLimitExceeded ();
272 va_start (List
, MsgFmt
);
273 PrintMessage ("warning", mSourceFileName
, mSourceFileLineNum
, ErrorCode
, OffendingText
, MsgFmt
, List
);
276 // Set status accordingly
278 if (mStatus
< STATUS_WARNING
) {
279 mStatus
= STATUS_WARNING
;
295 Print a warning message.
298 FileName - name of the file where the warning was detected, or the name
299 of the application that detected the warning
301 LineNumber - the line number where the warning was detected (parsers).
302 0 should be specified if the utility is not a parser.
304 MessageCode - an application-specific warning code that can be referenced in
307 Text - the text in question (parsers)
309 MsgFmt - the format string for the warning message. Can contain formatting
310 controls for use with varargs.
319 // If limits have been set, then check them
321 if (mPrintLimitsSet
) {
323 // See if we've exceeded our total count
325 if (mMaxWarningsPlusErrors
!= 0) {
326 if (mErrorCount
+ mWarningCount
> mMaxWarningsPlusErrors
) {
327 PrintLimitExceeded ();
332 // See if we've exceeded our warning count
334 if (mMaxWarnings
!= 0) {
335 if (mWarningCount
> mMaxWarnings
) {
336 PrintLimitExceeded ();
343 va_start (List
, MsgFmt
);
344 PrintMessage ("warning", FileName
, LineNumber
, MessageCode
, Text
, MsgFmt
, List
);
347 // Set status accordingly
349 if (mStatus
< STATUS_WARNING
) {
350 mStatus
= STATUS_WARNING
;
366 Print a warning 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 MsgMask - an application-specific bitmask that, in combination with mDebugMsgMask,
375 determines if the debug message gets printed.
377 Text - the text in question (parsers)
379 MsgFmt - the format string for the debug message. Can contain formatting
380 controls for use with varargs.
389 // If the debug mask is not applicable, then do nothing.
391 if ((MsgMask
!= 0) && ((mDebugMsgMask
& MsgMask
) == 0)) {
395 va_start (List
, MsgFmt
);
396 PrintMessage ("debug", FileName
, LineNumber
, 0, Text
, MsgFmt
, List
);
414 Worker routine for all the utility printing services. Prints the message in
415 a format that Visual Studio will find when scanning build outputs for
419 Type - "warning" or "error" string to insert into the message to be
420 printed. The first character of this string (converted to uppercase)
421 is used to preceed the MessageCode value in the output string.
423 FileName - name of the file where the warning was detected, or the name
424 of the application that detected the warning
426 LineNumber - the line number where the warning was detected (parsers).
427 0 should be specified if the utility is not a parser.
429 MessageCode - an application-specific warning code that can be referenced in
432 Text - part of the message to print
434 MsgFmt - the format string for the message. Can contain formatting
435 controls for use with varargs.
436 List - the variable list.
442 If FileName == NULL then this utility will use the string passed into SetUtilityName().
444 LineNumber is only used if the caller is a parser, in which case FileName refers to the
447 Text and MsgFmt are both optional, though it would be of little use calling this function with
450 Output will typically be of the form:
451 <FileName>(<LineNumber>) : <Type> <Type[0]><MessageCode>: <Text> : <MsgFmt>
453 Parser (LineNumber != 0)
454 VfrCompile.cpp(330) : error E2660: AddVfrDataStructField : function does not take 2 parameters
455 Generic utility (LineNumber == 0)
456 UtilityName : error E1234 : Text string : MsgFmt string and args
460 CHAR8 Line
[MAX_LINE_LEN
];
461 CHAR8 Line2
[MAX_LINE_LEN
];
464 // If given a filename, then add it (and the line number) to the string.
465 // If there's no filename, then use the program name if provided.
467 if (FileName
!= NULL
) {
469 } else if (mUtilityName
[0] != 0) {
472 Cptr
= "Unknown utility";
476 if (LineNumber
!= 0) {
477 sprintf (Line2
, "(%d)", LineNumber
);
478 strcat (Line
, Line2
);
481 // Have to print an error code or Visual Studio won't find the
482 // message for you. It has to be decimal digits too.
484 sprintf (Line2
, " : %s %c%04d", Type
, toupper (Type
[0]), MessageCode
);
485 strcat (Line
, Line2
);
486 fprintf (stdout
, "%s", Line
);
488 // If offending text was provided, then print it
491 fprintf (stdout
, ": %s ", Text
);
494 // Print formatted message if provided
496 if (MsgFmt
!= NULL
) {
497 vsprintf (Line2
, MsgFmt
, List
);
498 fprintf (stdout
, ": %s", Line2
);
501 fprintf (stdout
, "\n");
506 CHAR8
*SourceFileName
,
512 Set the position in a file being parsed. This can be used to
513 print error messages deeper down in a parser.
516 SourceFileName - name of the source file being parsed
517 LineNum - line number of the source file being parsed
524 mSourceFileName
= SourceFileName
;
525 mSourceFileLineNum
= LineNum
;
535 All printed error/warning/debug messages follow the same format, and
536 typically will print a filename or utility name followed by the error
537 text. However if a filename is not passed to the print routines, then
538 they'll print the utility name if you call this function early in your
539 app to set the utility name.
542 UtilityName - name of the utility, which will be printed with all
543 error/warning/debug messags.
551 // Save the name of the utility in our local variable. Make sure its
552 // length does not exceed our buffer.
554 if (UtilityName
!= NULL
) {
555 if (strlen (UtilityName
) >= sizeof (mUtilityName
)) {
556 Error (UtilityName
, 0, 0, "application error", "utility name length exceeds internal buffer size");
557 strncpy (mUtilityName
, UtilityName
, sizeof (mUtilityName
) - 1);
558 mUtilityName
[sizeof (mUtilityName
) - 1] = 0;
561 strcpy (mUtilityName
, UtilityName
);
564 Error (NULL
, 0, 0, "application error", "SetUtilityName() called with NULL utility name");
575 When you call Error() or Warning(), this module keeps track of it and
576 sets a local mStatus to STATUS_ERROR or STATUS_WARNING. When the utility
577 exits, it can call this function to get the status and use it as a return
584 Worst-case status reported, as defined by which print function was called.
598 Set the debug printing mask. This is used by the DebugMsg() function
599 to determine when/if a debug message should be printed.
602 DebugMask - bitmask, specific to the calling application
609 mDebugMsgMask
= DebugMask
;
616 UINT32 MaxWarningsPlusErrors
621 Set the limits of how many errors, warnings, and errors+warnings
625 MaxErrors - maximum number of error messages to print
626 MaxWarnings - maximum number of warning messages to print
627 MaxWarningsPlusErrors
628 - maximum number of errors+warnings to print
635 mMaxErrors
= MaxErrors
;
636 mMaxWarnings
= MaxWarnings
;
637 mMaxWarningsPlusErrors
= MaxWarningsPlusErrors
;
647 static INT8 mPrintLimitExceeded
= 0;
649 // If we've already printed the message, do nothing. Otherwise
650 // temporarily increase our print limits so we can pass one
651 // more message through.
653 if (mPrintLimitExceeded
== 0) {
654 mPrintLimitExceeded
++;
657 mMaxWarningsPlusErrors
++;
658 Error (NULL
, 0, 0, "error/warning print limit exceeded", NULL
);
661 mMaxWarningsPlusErrors
--;
667 TestUtilityMessages (
671 char *ArgStr
= "ArgString";
676 // Test without setting utility name
678 fprintf (stdout
, "* Testing without setting utility name\n");
679 fprintf (stdout
, "** Test debug message not printed\n");
680 DebugMsg (NULL
, 0, 0x00000001, NULL
, NULL
);
681 fprintf (stdout
, "** Test warning with two strings and two args\n");
682 Warning (NULL
, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
683 fprintf (stdout
, "** Test error with two strings and two args\n");
684 Warning (NULL
, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
685 fprintf (stdout
, "** Test parser warning with nothing\n");
686 ParserWarning (0, NULL
, NULL
);
687 fprintf (stdout
, "** Test parser error with nothing\n");
688 ParserError (0, NULL
, NULL
);
690 // Test with utility name set now
692 fprintf (stdout
, "** Testingin with utility name set\n");
693 SetUtilityName ("MyUtilityName");
698 fprintf (stdout
, "** Test debug message with one string\n");
699 DebugMsg (NULL
, 0, 0x00000002, "Text1", NULL
);
700 fprintf (stdout
, "** Test debug message with one string\n");
701 DebugMsg (NULL
, 0, 0x00000002, NULL
, "Text2");
702 fprintf (stdout
, "** Test debug message with two strings\n");
703 DebugMsg (NULL
, 0, 0x00000002, "Text1", "Text2");
704 fprintf (stdout
, "** Test debug message with two strings and two args\n");
705 DebugMsg (NULL
, 0, 0x00000002, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
707 // Test warning prints
709 fprintf (stdout
, "** Test warning with no strings\n");
710 Warning (NULL
, 0, 1234, NULL
, NULL
);
711 fprintf (stdout
, "** Test warning with one string\n");
712 Warning (NULL
, 0, 1234, "Text1", NULL
);
713 fprintf (stdout
, "** Test warning with one string\n");
714 Warning (NULL
, 0, 1234, NULL
, "Text2");
715 fprintf (stdout
, "** Test warning with two strings and two args\n");
716 Warning (NULL
, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
720 fprintf (stdout
, "** Test error with no strings\n");
721 Error (NULL
, 0, 1234, NULL
, NULL
);
722 fprintf (stdout
, "** Test error with one string\n");
723 Error (NULL
, 0, 1234, "Text1", NULL
);
724 fprintf (stdout
, "** Test error with one string\n");
725 Error (NULL
, 0, 1234, NULL
, "Text2");
726 fprintf (stdout
, "** Test error with two strings and two args\n");
727 Error (NULL
, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
729 // Test parser prints
731 fprintf (stdout
, "** Test parser errors\n");
732 ParserSetPosition (__FILE__
, __LINE__
+ 1);
733 ParserError (1234, NULL
, NULL
);
734 ParserSetPosition (__FILE__
, __LINE__
+ 1);
735 ParserError (1234, "Text1", NULL
);
736 ParserSetPosition (__FILE__
, __LINE__
+ 1);
737 ParserError (1234, NULL
, "Text2");
738 ParserSetPosition (__FILE__
, __LINE__
+ 1);
739 ParserError (1234, "Text1", "Text2");
740 ParserSetPosition (__FILE__
, __LINE__
+ 1);
741 ParserError (1234, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
743 fprintf (stdout
, "** Test parser warnings\n");
744 ParserSetPosition (__FILE__
, __LINE__
+ 1);
745 ParserWarning (4321, NULL
, NULL
);
746 ParserSetPosition (__FILE__
, __LINE__
+ 1);
747 ParserWarning (4321, "Text1", NULL
);
748 ParserSetPosition (__FILE__
, __LINE__
+ 1);
749 ParserWarning (4321, NULL
, "Text2");
750 ParserSetPosition (__FILE__
, __LINE__
+ 1);
751 ParserWarning (4321, "Text1", "Text2");
752 ParserSetPosition (__FILE__
, __LINE__
+ 1);
753 ParserWarning (4321, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);