3 Copyright (c) 2004, 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"
31 #define MAX_LINE_LEN 200
34 // Declare module globals for keeping track of the the utility's
35 // name and other settings.
37 static STATUS mStatus
= STATUS_SUCCESS
;
38 static INT8 mUtilityName
[50] = { 0 };
39 static UINT32 mDebugMsgMask
= 0;
40 static INT8
*mSourceFileName
= NULL
;
41 static UINT32 mSourceFileLineNum
= 0;
42 static UINT32 mErrorCount
= 0;
43 static UINT32 mWarningCount
= 0;
44 static UINT32 mMaxErrors
= 0;
45 static UINT32 mMaxWarnings
= 0;
46 static UINT32 mMaxWarningsPlusErrors
= 0;
47 static INT8 mPrintLimitsSet
= 0;
79 Prints an error message.
82 All arguments are optional, though the printed message may be useless if
83 at least something valid is not specified.
85 FileName - name of the file or application. If not specified, then the
86 utilty name (as set by the utility calling SetUtilityName()
87 earlier) is used. Otherwise "Unknown utility" is used.
89 LineNumber - the line number of error, typically used by parsers. If the
90 utility is not a parser, then 0 should be specified. Otherwise
91 the FileName and LineNumber info can be used to cause
92 MS Visual Studio to jump to the error.
94 MessageCode - an application-specific error code that can be referenced in
97 Text - the text in question, typically used by parsers.
99 MsgFmt - the format string for the error message. Can contain formatting
100 controls for use with the varargs.
106 We print the following (similar to the Warn() and Debug()
108 Typical error/warning message format:
110 bin\VfrCompile.cpp(330) : error C2660: 'AddVfrDataStructField' : function does not take 2 parameters
112 BUGBUG -- these three utility functions are almost identical, and
113 should be modified to share code.
115 Visual Studio does not find error messages with:
129 // If limits have been set, then check that we have not exceeded them
131 if (mPrintLimitsSet
) {
133 // See if we've exceeded our total count
135 if (mMaxWarningsPlusErrors
!= 0) {
136 if (mErrorCount
+ mWarningCount
> mMaxWarningsPlusErrors
) {
137 PrintLimitExceeded ();
142 // See if we've exceeded our error count
144 if (mMaxErrors
!= 0) {
145 if (mErrorCount
> mMaxErrors
) {
146 PrintLimitExceeded ();
153 va_start (List
, MsgFmt
);
154 PrintMessage ("error", FileName
, LineNumber
, MessageCode
, Text
, MsgFmt
, List
);
157 // Set status accordingly
159 if (mStatus
< STATUS_ERROR
) {
160 mStatus
= STATUS_ERROR
;
174 Print a parser error, using the source file name and line number
175 set by a previous call to SetParserPosition().
178 MessageCode - application-specific error code
179 Text - text to print in the error message
180 MsgFmt - format string to print at the end of the error message
189 // If limits have been set, then check them
191 if (mPrintLimitsSet
) {
193 // See if we've exceeded our total count
195 if (mMaxWarningsPlusErrors
!= 0) {
196 if (mErrorCount
+ mWarningCount
> mMaxWarningsPlusErrors
) {
197 PrintLimitExceeded ();
202 // See if we've exceeded our error count
204 if (mMaxErrors
!= 0) {
205 if (mErrorCount
> mMaxErrors
) {
206 PrintLimitExceeded ();
213 va_start (List
, MsgFmt
);
214 PrintMessage ("error", mSourceFileName
, mSourceFileLineNum
, MessageCode
, Text
, MsgFmt
, List
);
217 // Set status accordingly
219 if (mStatus
< STATUS_ERROR
) {
220 mStatus
= STATUS_ERROR
;
234 Print a parser warning, using the source file name and line number
235 set by a previous call to SetParserPosition().
238 ErrorCode - application-specific error code
239 OffendingText - text to print in the warning message
240 MsgFmt - format string to print at the end of the warning message
249 // If limits have been set, then check them
251 if (mPrintLimitsSet
) {
253 // See if we've exceeded our total count
255 if (mMaxWarningsPlusErrors
!= 0) {
256 if (mErrorCount
+ mWarningCount
> mMaxWarningsPlusErrors
) {
257 PrintLimitExceeded ();
262 // See if we've exceeded our warning count
264 if (mMaxWarnings
!= 0) {
265 if (mWarningCount
> mMaxWarnings
) {
266 PrintLimitExceeded ();
273 va_start (List
, MsgFmt
);
274 PrintMessage ("warning", mSourceFileName
, mSourceFileLineNum
, ErrorCode
, OffendingText
, MsgFmt
, List
);
277 // Set status accordingly
279 if (mStatus
< STATUS_WARNING
) {
280 mStatus
= STATUS_WARNING
;
296 Print a warning message.
299 FileName - name of the file where the warning was detected, or the name
300 of the application that detected the warning
302 LineNumber - the line number where the warning was detected (parsers).
303 0 should be specified if the utility is not a parser.
305 MessageCode - an application-specific warning code that can be referenced in
308 Text - the text in question (parsers)
310 MsgFmt - the format string for the warning message. Can contain formatting
311 controls for use with varargs.
320 // If limits have been set, then check them
322 if (mPrintLimitsSet
) {
324 // See if we've exceeded our total count
326 if (mMaxWarningsPlusErrors
!= 0) {
327 if (mErrorCount
+ mWarningCount
> mMaxWarningsPlusErrors
) {
328 PrintLimitExceeded ();
333 // See if we've exceeded our warning count
335 if (mMaxWarnings
!= 0) {
336 if (mWarningCount
> mMaxWarnings
) {
337 PrintLimitExceeded ();
344 va_start (List
, MsgFmt
);
345 PrintMessage ("warning", FileName
, LineNumber
, MessageCode
, Text
, MsgFmt
, List
);
348 // Set status accordingly
350 if (mStatus
< STATUS_WARNING
) {
351 mStatus
= STATUS_WARNING
;
367 Print a warning message.
370 FileName - typically the name of the utility printing the debug message, but
371 can be the name of a file being parsed.
373 LineNumber - the line number in FileName (parsers)
375 MsgMask - an application-specific bitmask that, in combination with mDebugMsgMask,
376 determines if the debug message gets printed.
378 Text - the text in question (parsers)
380 MsgFmt - the format string for the debug message. Can contain formatting
381 controls for use with varargs.
390 // If the debug mask is not applicable, then do nothing.
392 if ((MsgMask
!= 0) && ((mDebugMsgMask
& MsgMask
) == 0)) {
396 va_start (List
, MsgFmt
);
397 PrintMessage ("debug", FileName
, LineNumber
, 0, Text
, MsgFmt
, List
);
415 Worker routine for all the utility printing services. Prints the message in
416 a format that Visual Studio will find when scanning build outputs for
420 Type - "warning" or "error" string to insert into the message to be
421 printed. The first character of this string (converted to uppercase)
422 is used to preceed the MessageCode value in the output string.
424 FileName - name of the file where the warning was detected, or the name
425 of the application that detected the warning
427 LineNumber - the line number where the warning was detected (parsers).
428 0 should be specified if the utility is not a parser.
430 MessageCode - an application-specific warning code that can be referenced in
433 Text - part of the message to print
435 MsgFmt - the format string for the message. Can contain formatting
436 controls for use with varargs.
437 List - the variable list.
443 If FileName == NULL then this utility will use the string passed into SetUtilityName().
445 LineNumber is only used if the caller is a parser, in which case FileName refers to the
448 Text and MsgFmt are both optional, though it would be of little use calling this function with
451 Output will typically be of the form:
452 <FileName>(<LineNumber>) : <Type> <Type[0]><MessageCode>: <Text> : <MsgFmt>
454 Parser (LineNumber != 0)
455 VfrCompile.cpp(330) : error E2660: AddVfrDataStructField : function does not take 2 parameters
456 Generic utility (LineNumber == 0)
457 UtilityName : error E1234 : Text string : MsgFmt string and args
461 INT8 Line
[MAX_LINE_LEN
];
462 INT8 Line2
[MAX_LINE_LEN
];
465 // If given a filename, then add it (and the line number) to the string.
466 // If there's no filename, then use the program name if provided.
468 if (FileName
!= NULL
) {
470 } else if (mUtilityName
[0] != 0) {
473 Cptr
= "Unknown utility";
477 if (LineNumber
!= 0) {
478 sprintf (Line2
, "(%d)", LineNumber
);
479 strcat (Line
, Line2
);
482 // Have to print an error code or Visual Studio won't find the
483 // message for you. It has to be decimal digits too.
485 sprintf (Line2
, " : %s %c%04d", Type
, toupper (Type
[0]), MessageCode
);
486 strcat (Line
, Line2
);
487 fprintf (stdout
, "%s", Line
);
489 // If offending text was provided, then print it
492 fprintf (stdout
, ": %s ", Text
);
495 // Print formatted message if provided
497 if (MsgFmt
!= NULL
) {
498 vsprintf (Line2
, MsgFmt
, List
);
499 fprintf (stdout
, ": %s", Line2
);
502 fprintf (stdout
, "\n");
507 INT8
*SourceFileName
,
513 Set the position in a file being parsed. This can be used to
514 print error messages deeper down in a parser.
517 SourceFileName - name of the source file being parsed
518 LineNum - line number of the source file being parsed
525 mSourceFileName
= SourceFileName
;
526 mSourceFileLineNum
= LineNum
;
536 All printed error/warning/debug messages follow the same format, and
537 typically will print a filename or utility name followed by the error
538 text. However if a filename is not passed to the print routines, then
539 they'll print the utility name if you call this function early in your
540 app to set the utility name.
543 UtilityName - name of the utility, which will be printed with all
544 error/warning/debug messags.
552 // Save the name of the utility in our local variable. Make sure its
553 // length does not exceed our buffer.
555 if (UtilityName
!= NULL
) {
556 if (strlen (UtilityName
) >= sizeof (mUtilityName
)) {
557 Error (UtilityName
, 0, 0, "application error", "utility name length exceeds internal buffer size");
558 strncpy (mUtilityName
, UtilityName
, sizeof (mUtilityName
) - 1);
559 mUtilityName
[sizeof (mUtilityName
) - 1] = 0;
562 strcpy (mUtilityName
, UtilityName
);
565 Error (NULL
, 0, 0, "application error", "SetUtilityName() called with NULL utility name");
576 When you call Error() or Warning(), this module keeps track of it and
577 sets a local mStatus to STATUS_ERROR or STATUS_WARNING. When the utility
578 exits, it can call this function to get the status and use it as a return
585 Worst-case status reported, as defined by which print function was called.
599 Set the debug printing mask. This is used by the DebugMsg() function
600 to determine when/if a debug message should be printed.
603 DebugMask - bitmask, specific to the calling application
610 mDebugMsgMask
= DebugMask
;
617 UINT32 MaxWarningsPlusErrors
622 Set the limits of how many errors, warnings, and errors+warnings
626 MaxErrors - maximum number of error messages to print
627 MaxWarnings - maximum number of warning messages to print
628 MaxWarningsPlusErrors
629 - maximum number of errors+warnings to print
636 mMaxErrors
= MaxErrors
;
637 mMaxWarnings
= MaxWarnings
;
638 mMaxWarningsPlusErrors
= MaxWarningsPlusErrors
;
648 static INT8 mPrintLimitExceeded
= 0;
650 // If we've already printed the message, do nothing. Otherwise
651 // temporarily increase our print limits so we can pass one
652 // more message through.
654 if (mPrintLimitExceeded
== 0) {
655 mPrintLimitExceeded
++;
658 mMaxWarningsPlusErrors
++;
659 Error (NULL
, 0, 0, "error/warning print limit exceeded", NULL
);
662 mMaxWarningsPlusErrors
--;
668 TestUtilityMessages (
672 char *ArgStr
= "ArgString";
677 // Test without setting utility name
679 fprintf (stdout
, "* Testing without setting utility name\n");
680 fprintf (stdout
, "** Test debug message not printed\n");
681 DebugMsg (NULL
, 0, 0x00000001, NULL
, NULL
);
682 fprintf (stdout
, "** Test warning with two strings and two args\n");
683 Warning (NULL
, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
684 fprintf (stdout
, "** Test error with two strings and two args\n");
685 Warning (NULL
, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
686 fprintf (stdout
, "** Test parser warning with nothing\n");
687 ParserWarning (0, NULL
, NULL
);
688 fprintf (stdout
, "** Test parser error with nothing\n");
689 ParserError (0, NULL
, NULL
);
691 // Test with utility name set now
693 fprintf (stdout
, "** Testingin with utility name set\n");
694 SetUtilityName ("MyUtilityName");
699 fprintf (stdout
, "** Test debug message with one string\n");
700 DebugMsg (NULL
, 0, 0x00000002, "Text1", NULL
);
701 fprintf (stdout
, "** Test debug message with one string\n");
702 DebugMsg (NULL
, 0, 0x00000002, NULL
, "Text2");
703 fprintf (stdout
, "** Test debug message with two strings\n");
704 DebugMsg (NULL
, 0, 0x00000002, "Text1", "Text2");
705 fprintf (stdout
, "** Test debug message with two strings and two args\n");
706 DebugMsg (NULL
, 0, 0x00000002, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
708 // Test warning prints
710 fprintf (stdout
, "** Test warning with no strings\n");
711 Warning (NULL
, 0, 1234, NULL
, NULL
);
712 fprintf (stdout
, "** Test warning with one string\n");
713 Warning (NULL
, 0, 1234, "Text1", NULL
);
714 fprintf (stdout
, "** Test warning with one string\n");
715 Warning (NULL
, 0, 1234, NULL
, "Text2");
716 fprintf (stdout
, "** Test warning with two strings and two args\n");
717 Warning (NULL
, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
721 fprintf (stdout
, "** Test error with no strings\n");
722 Error (NULL
, 0, 1234, NULL
, NULL
);
723 fprintf (stdout
, "** Test error with one string\n");
724 Error (NULL
, 0, 1234, "Text1", NULL
);
725 fprintf (stdout
, "** Test error with one string\n");
726 Error (NULL
, 0, 1234, NULL
, "Text2");
727 fprintf (stdout
, "** Test error with two strings and two args\n");
728 Error (NULL
, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
730 // Test parser prints
732 fprintf (stdout
, "** Test parser errors\n");
733 ParserSetPosition (__FILE__
, __LINE__
+ 1);
734 ParserError (1234, NULL
, NULL
);
735 ParserSetPosition (__FILE__
, __LINE__
+ 1);
736 ParserError (1234, "Text1", NULL
);
737 ParserSetPosition (__FILE__
, __LINE__
+ 1);
738 ParserError (1234, NULL
, "Text2");
739 ParserSetPosition (__FILE__
, __LINE__
+ 1);
740 ParserError (1234, "Text1", "Text2");
741 ParserSetPosition (__FILE__
, __LINE__
+ 1);
742 ParserError (1234, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);
744 fprintf (stdout
, "** Test parser warnings\n");
745 ParserSetPosition (__FILE__
, __LINE__
+ 1);
746 ParserWarning (4321, NULL
, NULL
);
747 ParserSetPosition (__FILE__
, __LINE__
+ 1);
748 ParserWarning (4321, "Text1", NULL
);
749 ParserSetPosition (__FILE__
, __LINE__
+ 1);
750 ParserWarning (4321, NULL
, "Text2");
751 ParserSetPosition (__FILE__
, __LINE__
+ 1);
752 ParserWarning (4321, "Text1", "Text2");
753 ParserSetPosition (__FILE__
, __LINE__
+ 1);
754 ParserWarning (4321, "Text1", "Text2 %s 0x%X", ArgStr
, ArgInt
);