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