]> git.proxmox.com Git - mirror_edk2.git/blob - EdkCompatibilityPkg/Sample/Tools/Source/Common/EfiUtilityMsgs.c
Add in the 1st version of ECP.
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Tools / Source / Common / EfiUtilityMsgs.c
1 /*++
2
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
8
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.
11
12 Module Name:
13
14 EfiUtilityMsgs.c
15
16 Abstract:
17
18 EFI tools utility functions to display warning, error, and informational
19 messages.
20
21 --*/
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <stdarg.h>
27
28 #include "Tiano.h"
29 #include "EfiUtilityMsgs.h"
30
31 #define MAX_LINE_LEN 200
32
33 //
34 // Declare module globals for keeping track of the the utility's
35 // name and other settings.
36 //
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;
48
49 static
50 void
51 PrintMessage (
52 INT8 *Type,
53 INT8 *FileName,
54 UINT32 LineNumber,
55 UINT32 MessageCode,
56 INT8 *Text,
57 INT8 *MsgFmt,
58 va_list List
59 );
60
61 static
62 void
63 PrintLimitExceeded (
64 VOID
65 );
66
67 void
68 Error (
69 INT8 *FileName,
70 UINT32 LineNumber,
71 UINT32 MessageCode,
72 INT8 *Text,
73 INT8 *MsgFmt,
74 ...
75 )
76 /*++
77
78 Routine Description:
79 Prints an error message.
80
81 Arguments:
82 All arguments are optional, though the printed message may be useless if
83 at least something valid is not specified.
84
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.
88
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.
93
94 MessageCode - an application-specific error code that can be referenced in
95 other documentation.
96
97 Text - the text in question, typically used by parsers.
98
99 MsgFmt - the format string for the error message. Can contain formatting
100 controls for use with the varargs.
101
102 Returns:
103 None.
104
105 Notes:
106 We print the following (similar to the Warn() and Debug()
107 W
108 Typical error/warning message format:
109
110 bin\VfrCompile.cpp(330) : error C2660: 'AddVfrDataStructField' : function does not take 2 parameters
111
112 BUGBUG -- these three utility functions are almost identical, and
113 should be modified to share code.
114
115 Visual Studio does not find error messages with:
116
117 " error :"
118 " error 1:"
119 " error c1:"
120 " error 1000:"
121 " error c100:"
122
123 It does find:
124 " error c1000:"
125 --*/
126 {
127 va_list List;
128 //
129 // If limits have been set, then check that we have not exceeded them
130 //
131 if (mPrintLimitsSet) {
132 //
133 // See if we've exceeded our total count
134 //
135 if (mMaxWarningsPlusErrors != 0) {
136 if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) {
137 PrintLimitExceeded ();
138 return ;
139 }
140 }
141 //
142 // See if we've exceeded our error count
143 //
144 if (mMaxErrors != 0) {
145 if (mErrorCount > mMaxErrors) {
146 PrintLimitExceeded ();
147 return ;
148 }
149 }
150 }
151
152 mErrorCount++;
153 va_start (List, MsgFmt);
154 PrintMessage ("error", FileName, LineNumber, MessageCode, Text, MsgFmt, List);
155 va_end (List);
156 //
157 // Set status accordingly
158 //
159 if (mStatus < STATUS_ERROR) {
160 mStatus = STATUS_ERROR;
161 }
162 }
163
164 void
165 ParserError (
166 UINT32 MessageCode,
167 INT8 *Text,
168 INT8 *MsgFmt,
169 ...
170 )
171 /*++
172
173 Routine Description:
174 Print a parser error, using the source file name and line number
175 set by a previous call to SetParserPosition().
176
177 Arguments:
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
181
182 Returns:
183 NA
184
185 --*/
186 {
187 va_list List;
188 //
189 // If limits have been set, then check them
190 //
191 if (mPrintLimitsSet) {
192 //
193 // See if we've exceeded our total count
194 //
195 if (mMaxWarningsPlusErrors != 0) {
196 if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) {
197 PrintLimitExceeded ();
198 return ;
199 }
200 }
201 //
202 // See if we've exceeded our error count
203 //
204 if (mMaxErrors != 0) {
205 if (mErrorCount > mMaxErrors) {
206 PrintLimitExceeded ();
207 return ;
208 }
209 }
210 }
211
212 mErrorCount++;
213 va_start (List, MsgFmt);
214 PrintMessage ("error", mSourceFileName, mSourceFileLineNum, MessageCode, Text, MsgFmt, List);
215 va_end (List);
216 //
217 // Set status accordingly
218 //
219 if (mStatus < STATUS_ERROR) {
220 mStatus = STATUS_ERROR;
221 }
222 }
223
224 void
225 ParserWarning (
226 UINT32 ErrorCode,
227 INT8 *OffendingText,
228 INT8 *MsgFmt,
229 ...
230 )
231 /*++
232
233 Routine Description:
234 Print a parser warning, using the source file name and line number
235 set by a previous call to SetParserPosition().
236
237 Arguments:
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
241
242 Returns:
243 NA
244
245 --*/
246 {
247 va_list List;
248 //
249 // If limits have been set, then check them
250 //
251 if (mPrintLimitsSet) {
252 //
253 // See if we've exceeded our total count
254 //
255 if (mMaxWarningsPlusErrors != 0) {
256 if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) {
257 PrintLimitExceeded ();
258 return ;
259 }
260 }
261 //
262 // See if we've exceeded our warning count
263 //
264 if (mMaxWarnings != 0) {
265 if (mWarningCount > mMaxWarnings) {
266 PrintLimitExceeded ();
267 return ;
268 }
269 }
270 }
271
272 mWarningCount++;
273 va_start (List, MsgFmt);
274 PrintMessage ("warning", mSourceFileName, mSourceFileLineNum, ErrorCode, OffendingText, MsgFmt, List);
275 va_end (List);
276 //
277 // Set status accordingly
278 //
279 if (mStatus < STATUS_WARNING) {
280 mStatus = STATUS_WARNING;
281 }
282 }
283
284 void
285 Warning (
286 INT8 *FileName,
287 UINT32 LineNumber,
288 UINT32 MessageCode,
289 INT8 *Text,
290 INT8 *MsgFmt,
291 ...
292 )
293 /*++
294
295 Routine Description:
296 Print a warning message.
297
298 Arguments:
299 FileName - name of the file where the warning was detected, or the name
300 of the application that detected the warning
301
302 LineNumber - the line number where the warning was detected (parsers).
303 0 should be specified if the utility is not a parser.
304
305 MessageCode - an application-specific warning code that can be referenced in
306 other documentation.
307
308 Text - the text in question (parsers)
309
310 MsgFmt - the format string for the warning message. Can contain formatting
311 controls for use with varargs.
312
313 Returns:
314 None.
315
316 --*/
317 {
318 va_list List;
319 //
320 // If limits have been set, then check them
321 //
322 if (mPrintLimitsSet) {
323 //
324 // See if we've exceeded our total count
325 //
326 if (mMaxWarningsPlusErrors != 0) {
327 if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) {
328 PrintLimitExceeded ();
329 return ;
330 }
331 }
332 //
333 // See if we've exceeded our warning count
334 //
335 if (mMaxWarnings != 0) {
336 if (mWarningCount > mMaxWarnings) {
337 PrintLimitExceeded ();
338 return ;
339 }
340 }
341 }
342
343 mWarningCount++;
344 va_start (List, MsgFmt);
345 PrintMessage ("warning", FileName, LineNumber, MessageCode, Text, MsgFmt, List);
346 va_end (List);
347 //
348 // Set status accordingly
349 //
350 if (mStatus < STATUS_WARNING) {
351 mStatus = STATUS_WARNING;
352 }
353 }
354
355 void
356 DebugMsg (
357 INT8 *FileName,
358 UINT32 LineNumber,
359 UINT32 MsgMask,
360 INT8 *Text,
361 INT8 *MsgFmt,
362 ...
363 )
364 /*++
365
366 Routine Description:
367 Print a warning message.
368
369 Arguments:
370 FileName - typically the name of the utility printing the debug message, but
371 can be the name of a file being parsed.
372
373 LineNumber - the line number in FileName (parsers)
374
375 MsgMask - an application-specific bitmask that, in combination with mDebugMsgMask,
376 determines if the debug message gets printed.
377
378 Text - the text in question (parsers)
379
380 MsgFmt - the format string for the debug message. Can contain formatting
381 controls for use with varargs.
382
383 Returns:
384 None.
385
386 --*/
387 {
388 va_list List;
389 //
390 // If the debug mask is not applicable, then do nothing.
391 //
392 if ((MsgMask != 0) && ((mDebugMsgMask & MsgMask) == 0)) {
393 return ;
394 }
395
396 va_start (List, MsgFmt);
397 PrintMessage ("debug", FileName, LineNumber, 0, Text, MsgFmt, List);
398 va_end (List);
399 }
400
401 static
402 void
403 PrintMessage (
404 INT8 *Type,
405 INT8 *FileName,
406 UINT32 LineNumber,
407 UINT32 MessageCode,
408 INT8 *Text,
409 INT8 *MsgFmt,
410 va_list List
411 )
412 /*++
413
414 Routine Description:
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
417 errors or warnings.
418
419 Arguments:
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.
423
424 FileName - name of the file where the warning was detected, or the name
425 of the application that detected the warning
426
427 LineNumber - the line number where the warning was detected (parsers).
428 0 should be specified if the utility is not a parser.
429
430 MessageCode - an application-specific warning code that can be referenced in
431 other documentation.
432
433 Text - part of the message to print
434
435 MsgFmt - the format string for the message. Can contain formatting
436 controls for use with varargs.
437 List - the variable list.
438
439 Returns:
440 None.
441
442 Notes:
443 If FileName == NULL then this utility will use the string passed into SetUtilityName().
444
445 LineNumber is only used if the caller is a parser, in which case FileName refers to the
446 file being parsed.
447
448 Text and MsgFmt are both optional, though it would be of little use calling this function with
449 them both NULL.
450
451 Output will typically be of the form:
452 <FileName>(<LineNumber>) : <Type> <Type[0]><MessageCode>: <Text> : <MsgFmt>
453
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
458
459 --*/
460 {
461 INT8 Line[MAX_LINE_LEN];
462 INT8 Line2[MAX_LINE_LEN];
463 INT8 *Cptr;
464 //
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.
467 //
468 if (FileName != NULL) {
469 Cptr = FileName;
470 } else if (mUtilityName[0] != 0) {
471 Cptr = mUtilityName;
472 } else {
473 Cptr = "Unknown utility";
474 }
475
476 strcpy (Line, Cptr);
477 if (LineNumber != 0) {
478 sprintf (Line2, "(%d)", LineNumber);
479 strcat (Line, Line2);
480 }
481 //
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.
484 //
485 sprintf (Line2, " : %s %c%04d", Type, toupper (Type[0]), MessageCode);
486 strcat (Line, Line2);
487 fprintf (stdout, "%s", Line);
488 //
489 // If offending text was provided, then print it
490 //
491 if (Text != NULL) {
492 fprintf (stdout, ": %s ", Text);
493 }
494 //
495 // Print formatted message if provided
496 //
497 if (MsgFmt != NULL) {
498 vsprintf (Line2, MsgFmt, List);
499 fprintf (stdout, ": %s", Line2);
500 }
501
502 fprintf (stdout, "\n");
503 }
504
505 void
506 ParserSetPosition (
507 INT8 *SourceFileName,
508 UINT32 LineNum
509 )
510 /*++
511
512 Routine Description:
513 Set the position in a file being parsed. This can be used to
514 print error messages deeper down in a parser.
515
516 Arguments:
517 SourceFileName - name of the source file being parsed
518 LineNum - line number of the source file being parsed
519
520 Returns:
521 NA
522
523 --*/
524 {
525 mSourceFileName = SourceFileName;
526 mSourceFileLineNum = LineNum;
527 }
528
529 void
530 SetUtilityName (
531 INT8 *UtilityName
532 )
533 /*++
534
535 Routine Description:
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.
541
542 Arguments:
543 UtilityName - name of the utility, which will be printed with all
544 error/warning/debug messags.
545
546 Returns:
547 NA
548
549 --*/
550 {
551 //
552 // Save the name of the utility in our local variable. Make sure its
553 // length does not exceed our buffer.
554 //
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;
560 return ;
561 } else {
562 strcpy (mUtilityName, UtilityName);
563 }
564 } else {
565 Error (NULL, 0, 0, "application error", "SetUtilityName() called with NULL utility name");
566 }
567 }
568
569 STATUS
570 GetUtilityStatus (
571 VOID
572 )
573 /*++
574
575 Routine Description:
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
579 value.
580
581 Arguments:
582 None.
583
584 Returns:
585 Worst-case status reported, as defined by which print function was called.
586
587 --*/
588 {
589 return mStatus;
590 }
591
592 void
593 SetDebugMsgMask (
594 UINT32 DebugMask
595 )
596 /*++
597
598 Routine Description:
599 Set the debug printing mask. This is used by the DebugMsg() function
600 to determine when/if a debug message should be printed.
601
602 Arguments:
603 DebugMask - bitmask, specific to the calling application
604
605 Returns:
606 NA
607
608 --*/
609 {
610 mDebugMsgMask = DebugMask;
611 }
612
613 void
614 SetPrintLimits (
615 UINT32 MaxErrors,
616 UINT32 MaxWarnings,
617 UINT32 MaxWarningsPlusErrors
618 )
619 /*++
620
621 Routine Description:
622 Set the limits of how many errors, warnings, and errors+warnings
623 we will print.
624
625 Arguments:
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
630
631 Returns:
632 NA
633
634 --*/
635 {
636 mMaxErrors = MaxErrors;
637 mMaxWarnings = MaxWarnings;
638 mMaxWarningsPlusErrors = MaxWarningsPlusErrors;
639 mPrintLimitsSet = 1;
640 }
641
642 static
643 void
644 PrintLimitExceeded (
645 VOID
646 )
647 {
648 static INT8 mPrintLimitExceeded = 0;
649 //
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.
653 //
654 if (mPrintLimitExceeded == 0) {
655 mPrintLimitExceeded++;
656 mMaxErrors++;
657 mMaxWarnings++;
658 mMaxWarningsPlusErrors++;
659 Error (NULL, 0, 0, "error/warning print limit exceeded", NULL);
660 mMaxErrors--;
661 mMaxWarnings--;
662 mMaxWarningsPlusErrors--;
663 }
664 }
665
666 #if 0
667 void
668 TestUtilityMessages (
669 VOID
670 )
671 {
672 char *ArgStr = "ArgString";
673 int ArgInt;
674
675 ArgInt = 0x12345678;
676 //
677 // Test without setting utility name
678 //
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);
690 //
691 // Test with utility name set now
692 //
693 fprintf (stdout, "** Testingin with utility name set\n");
694 SetUtilityName ("MyUtilityName");
695 //
696 // Test debug prints
697 //
698 SetDebugMsgMask (2);
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);
707 //
708 // Test warning prints
709 //
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);
718 //
719 // Test error prints
720 //
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);
729 //
730 // Test parser prints
731 //
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);
743
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);
755 }
756 #endif