Sync EDKII BaseTools to BaseTools project r1903.
[efi/edk2/.git] / edk2 / BaseTools / Source / C / Common / EfiUtilityMsgs.c
1 /** @file\r
2 \r
3 Copyright (c) 2004 - 2008, Intel Corporation\r
4 All rights reserved. This program and the accompanying materials\r
5 are licensed and made available under the terms and conditions of the BSD License\r
6 which accompanies this distribution.  The full text of the license may be found at\r
7 http://opensource.org/licenses/bsd-license.php\r
8 \r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11 \r
12 Module Name:\r
13 \r
14   EfiUtilityMsgs.c\r
15 \r
16 Abstract:\r
17 \r
18   EFI tools utility functions to display warning, error, and informational\r
19   messages.\r
20 \r
21 --*/\r
22 \r
23 #include <stdio.h>\r
24 #include <string.h>\r
25 #include <ctype.h>\r
26 #include <stdarg.h>\r
27 #include <time.h>\r
28 \r
29 #include "EfiUtilityMsgs.h"\r
30 \r
31 //\r
32 // Declare module globals for keeping track of the the utility's\r
33 // name and other settings.\r
34 //\r
35 STATIC STATUS mStatus                 = STATUS_SUCCESS;\r
36 STATIC CHAR8  mUtilityName[50]        = { 0 };\r
37 STATIC UINT64 mPrintLogLevel          = INFO_LOG_LEVEL;\r
38 STATIC CHAR8  *mSourceFileName        = NULL;\r
39 STATIC UINT32 mSourceFileLineNum      = 0;\r
40 STATIC UINT32 mErrorCount             = 0;\r
41 STATIC UINT32 mWarningCount           = 0;\r
42 STATIC UINT32 mMaxErrors              = 0;\r
43 STATIC UINT32 mMaxWarnings            = 0;\r
44 STATIC UINT32 mMaxWarningsPlusErrors  = 0;\r
45 STATIC INT8   mPrintLimitsSet         = 0;\r
46 \r
47 STATIC\r
48 VOID\r
49 PrintLimitExceeded (\r
50   VOID\r
51   );\r
52 \r
53 VOID\r
54 Error (\r
55   CHAR8   *FileName,\r
56   UINT32  LineNumber,\r
57   UINT32  MessageCode,\r
58   CHAR8   *Text,\r
59   CHAR8   *MsgFmt,\r
60   ...\r
61   )\r
62 /*++\r
63 \r
64 Routine Description:\r
65   Prints an error message.\r
66 \r
67 Arguments:\r
68   All arguments are optional, though the printed message may be useless if\r
69   at least something valid is not specified.\r
70 \r
71   FileName - name of the file or application. If not specified, then the\r
72              utilty name (as set by the utility calling SetUtilityName()\r
73              earlier) is used. Otherwise "Unknown utility" is used.\r
74 \r
75   LineNumber - the line number of error, typically used by parsers. If the\r
76                utility is not a parser, then 0 should be specified. Otherwise\r
77                the FileName and LineNumber info can be used to cause\r
78                MS Visual Studio to jump to the error.\r
79 \r
80   MessageCode - an application-specific error code that can be referenced in\r
81               other documentation.\r
82 \r
83   Text        - the text in question, typically used by parsers.\r
84 \r
85   MsgFmt - the format string for the error message. Can contain formatting\r
86            controls for use with the varargs.\r
87 \r
88 Returns:\r
89   None.\r
90 \r
91 Notes:\r
92   We print the following (similar to the Warn() and Debug()\r
93   W\r
94   Typical error/warning message format:\r
95 \r
96   bin\VfrCompile.cpp(330) : error C2660: 'AddVfrDataStructField' : function does not take 2 parameters\r
97 \r
98   BUGBUG -- these three utility functions are almost identical, and\r
99   should be modified to share code.\r
100 \r
101   Visual Studio does not find error messages with:\r
102 \r
103      " error :"\r
104      " error 1:"\r
105      " error c1:"\r
106      " error 1000:"\r
107      " error c100:"\r
108 \r
109   It does find:\r
110      " error c1000:"\r
111 --*/\r
112 {\r
113   va_list List;\r
114   //\r
115   // If limits have been set, then check that we have not exceeded them\r
116   //\r
117   if (mPrintLimitsSet) {\r
118     //\r
119     // See if we've exceeded our total count\r
120     //\r
121     if (mMaxWarningsPlusErrors != 0) {\r
122       if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) {\r
123         PrintLimitExceeded ();\r
124         return ;\r
125       }\r
126     }\r
127     //\r
128     // See if we've exceeded our error count\r
129     //\r
130     if (mMaxErrors != 0) {\r
131       if (mErrorCount > mMaxErrors) {\r
132         PrintLimitExceeded ();\r
133         return ;\r
134       }\r
135     }\r
136   }\r
137 \r
138   mErrorCount++;\r
139   va_start (List, MsgFmt);\r
140   PrintMessage ("ERROR", FileName, LineNumber, MessageCode, Text, MsgFmt, List);\r
141   va_end (List);\r
142 }\r
143 \r
144 VOID\r
145 ParserError (\r
146   UINT32  MessageCode,\r
147   CHAR8   *Text,\r
148   CHAR8   *MsgFmt,\r
149   ...\r
150   )\r
151 /*++\r
152 \r
153 Routine Description:\r
154   Print a parser error, using the source file name and line number\r
155   set by a previous call to SetParserPosition().\r
156 \r
157 Arguments:\r
158   MessageCode   - application-specific error code\r
159   Text          - text to print in the error message\r
160   MsgFmt        - format string to print at the end of the error message\r
161 \r
162 Returns:\r
163   NA\r
164 \r
165 --*/\r
166 {\r
167   va_list List;\r
168   //\r
169   // If limits have been set, then check them\r
170   //\r
171   if (mPrintLimitsSet) {\r
172     //\r
173     // See if we've exceeded our total count\r
174     //\r
175     if (mMaxWarningsPlusErrors != 0) {\r
176       if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) {\r
177         PrintLimitExceeded ();\r
178         return ;\r
179       }\r
180     }\r
181     //\r
182     // See if we've exceeded our error count\r
183     //\r
184     if (mMaxErrors != 0) {\r
185       if (mErrorCount > mMaxErrors) {\r
186         PrintLimitExceeded ();\r
187         return ;\r
188       }\r
189     }\r
190   }\r
191 \r
192   mErrorCount++;\r
193   va_start (List, MsgFmt);\r
194   PrintMessage ("ERROR", mSourceFileName, mSourceFileLineNum, MessageCode, Text, MsgFmt, List);\r
195   va_end (List);\r
196 }\r
197 \r
198 VOID\r
199 ParserWarning (\r
200   UINT32  ErrorCode,\r
201   CHAR8   *OffendingText,\r
202   CHAR8   *MsgFmt,\r
203   ...\r
204   )\r
205 /*++\r
206 \r
207 Routine Description:\r
208   Print a parser warning, using the source file name and line number\r
209   set by a previous call to SetParserPosition().\r
210 \r
211 Arguments:\r
212   ErrorCode     - application-specific error code\r
213   OffendingText - text to print in the warning message\r
214   MsgFmt        - format string to print at the end of the warning message\r
215 \r
216 Returns:\r
217   NA\r
218 \r
219 --*/\r
220 {\r
221   va_list List;\r
222   //\r
223   // If limits have been set, then check them\r
224   //\r
225   if (mPrintLimitsSet) {\r
226     //\r
227     // See if we've exceeded our total count\r
228     //\r
229     if (mMaxWarningsPlusErrors != 0) {\r
230       if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) {\r
231         PrintLimitExceeded ();\r
232         return ;\r
233       }\r
234     }\r
235     //\r
236     // See if we've exceeded our warning count\r
237     //\r
238     if (mMaxWarnings != 0) {\r
239       if (mWarningCount > mMaxWarnings) {\r
240         PrintLimitExceeded ();\r
241         return ;\r
242       }\r
243     }\r
244   }\r
245 \r
246   mWarningCount++;\r
247   va_start (List, MsgFmt);\r
248   PrintMessage ("WARNING", mSourceFileName, mSourceFileLineNum, ErrorCode, OffendingText, MsgFmt, List);\r
249   va_end (List);\r
250   //\r
251   // Don't set warning status accordingly\r
252   //\r
253   //  if (mStatus < STATUS_WARNING) {\r
254   //    mStatus = STATUS_WARNING;\r
255   //  }\r
256 }\r
257 \r
258 VOID\r
259 Warning (\r
260   CHAR8   *FileName,\r
261   UINT32  LineNumber,\r
262   UINT32  MessageCode,\r
263   CHAR8   *Text,\r
264   CHAR8   *MsgFmt,\r
265   ...\r
266   )\r
267 /*++\r
268 \r
269 Routine Description:\r
270   Print a warning message.\r
271 \r
272 Arguments:\r
273   FileName    - name of the file where the warning was detected, or the name\r
274                 of the application that detected the warning\r
275 \r
276   LineNumber  - the line number where the warning was detected (parsers).\r
277                 0 should be specified if the utility is not a parser.\r
278 \r
279   MessageCode - an application-specific warning code that can be referenced in\r
280                 other documentation.\r
281 \r
282   Text        - the text in question (parsers)\r
283 \r
284   MsgFmt      - the format string for the warning message. Can contain formatting\r
285                 controls for use with varargs.\r
286 \r
287 Returns:\r
288   None.\r
289 \r
290 --*/\r
291 {\r
292   va_list List;\r
293 \r
294   //\r
295   // Current Print Level not output warning information.\r
296   //\r
297   if (WARNING_LOG_LEVEL < mPrintLogLevel) {\r
298     return;\r
299   }\r
300   //\r
301   // If limits have been set, then check them\r
302   //\r
303   if (mPrintLimitsSet) {\r
304     //\r
305     // See if we've exceeded our total count\r
306     //\r
307     if (mMaxWarningsPlusErrors != 0) {\r
308       if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) {\r
309         PrintLimitExceeded ();\r
310         return ;\r
311       }\r
312     }\r
313     //\r
314     // See if we've exceeded our warning count\r
315     //\r
316     if (mMaxWarnings != 0) {\r
317       if (mWarningCount > mMaxWarnings) {\r
318         PrintLimitExceeded ();\r
319         return ;\r
320       }\r
321     }\r
322   }\r
323 \r
324   mWarningCount++;\r
325   va_start (List, MsgFmt);\r
326   PrintMessage ("WARNING", FileName, LineNumber, MessageCode, Text, MsgFmt, List);\r
327   va_end (List);\r
328 }\r
329 \r
330 VOID\r
331 DebugMsg (\r
332   CHAR8   *FileName,\r
333   UINT32  LineNumber,\r
334   UINT64  MsgLevel,\r
335   CHAR8   *Text,\r
336   CHAR8   *MsgFmt,\r
337   ...\r
338   )\r
339 /*++\r
340 \r
341 Routine Description:\r
342   Print a Debug message.\r
343 \r
344 Arguments:\r
345   FileName    - typically the name of the utility printing the debug message, but\r
346                 can be the name of a file being parsed.\r
347 \r
348   LineNumber  - the line number in FileName (parsers)\r
349 \r
350   MsgLevel    - Debug message print level (0~9)\r
351 \r
352   Text        - the text in question (parsers)\r
353 \r
354   MsgFmt      - the format string for the debug message. Can contain formatting\r
355                 controls for use with varargs.\r
356 \r
357 Returns:\r
358   None.\r
359 \r
360 --*/\r
361 {\r
362   va_list List;\r
363   //\r
364   // If the debug level is less than current print level, then do nothing.\r
365   //\r
366   if (MsgLevel < mPrintLogLevel) {\r
367     return ;\r
368   }\r
369 \r
370   va_start (List, MsgFmt);\r
371   PrintMessage ("DEBUG", FileName, LineNumber, 0, Text, MsgFmt, List);\r
372   va_end (List);\r
373 }\r
374 \r
375 VOID\r
376 PrintMessage (\r
377   CHAR8   *Type,\r
378   CHAR8   *FileName,\r
379   UINT32  LineNumber,\r
380   UINT32  MessageCode,\r
381   CHAR8   *Text,\r
382   CHAR8   *MsgFmt,\r
383   va_list List\r
384   )\r
385 /*++\r
386 \r
387 Routine Description:\r
388   Worker routine for all the utility printing services. Prints the message in\r
389   a format that Visual Studio will find when scanning build outputs for\r
390   errors or warnings.\r
391 \r
392 Arguments:\r
393   Type        - "warning" or "error" string to insert into the message to be\r
394                 printed. The first character of this string (converted to uppercase)\r
395                 is used to preceed the MessageCode value in the output string.\r
396 \r
397   FileName    - name of the file where the warning was detected, or the name\r
398                 of the application that detected the warning\r
399 \r
400   LineNumber  - the line number where the warning was detected (parsers).\r
401                 0 should be specified if the utility is not a parser.\r
402 \r
403   MessageCode - an application-specific warning code that can be referenced in\r
404                 other documentation.\r
405 \r
406   Text        - part of the message to print\r
407 \r
408   MsgFmt      - the format string for the message. Can contain formatting\r
409                 controls for use with varargs.\r
410   List        - the variable list.\r
411 \r
412 Returns:\r
413   None.\r
414 \r
415 Notes:\r
416   If FileName == NULL then this utility will use the string passed into SetUtilityName().\r
417 \r
418   LineNumber is only used if the caller is a parser, in which case FileName refers to the\r
419   file being parsed.\r
420 \r
421   Text and MsgFmt are both optional, though it would be of little use calling this function with\r
422   them both NULL.\r
423 \r
424   Output will typically be of the form:\r
425     <FileName>(<LineNumber>) : <Type> <Type[0]><MessageCode>: <Text> : <MsgFmt>\r
426 \r
427     Parser (LineNumber != 0)\r
428       VfrCompile.cpp(330) : error E2660: AddVfrDataStructField : function does not take 2 parameters\r
429     Generic utility (LineNumber == 0)\r
430       UtilityName : error E1234 : Text string : MsgFmt string and args\r
431 \r
432 --*/\r
433 {\r
434   CHAR8       Line[MAX_LINE_LEN];\r
435   CHAR8       Line2[MAX_LINE_LEN];\r
436   CHAR8       *Cptr;\r
437   struct tm   *NewTime;\r
438   time_t      CurrentTime;\r
439 \r
440   //\r
441   // init local variable\r
442   //\r
443   Line[0] = '\0';\r
444   Line2[0] = '\0';\r
445 \r
446   //\r
447   // If given a filename, then add it (and the line number) to the string.\r
448   // If there's no filename, then use the program name if provided.\r
449   //\r
450   if (FileName != NULL) {\r
451     Cptr = FileName;\r
452   } else {\r
453     Cptr = NULL;\r
454   }\r
455 \r
456   if (strcmp (Type, "DEBUG") == 0) {\r
457     //\r
458     // Debug Message requires current time.\r
459     //\r
460     time (&CurrentTime);\r
461     NewTime = localtime (&CurrentTime);\r
462     fprintf (stdout, "%04d-%02d-%02d %02d:%02d:%02d",\r
463                      NewTime->tm_year + 1900,\r
464                      NewTime->tm_mon + 1,\r
465                      NewTime->tm_mday,\r
466                      NewTime->tm_hour,\r
467                      NewTime->tm_min,\r
468                      NewTime->tm_sec\r
469                      );\r
470     if (Cptr != NULL) {\r
471       sprintf (Line, ": %s", Cptr);\r
472       if (LineNumber != 0) {\r
473         sprintf (Line2, "(%u)", (unsigned) LineNumber);\r
474         strcat (Line, Line2);\r
475       }\r
476     }\r
477   } else {\r
478     //\r
479     // Error and Warning Information.\r
480     //\r
481     if (Cptr != NULL) {\r
482       if (mUtilityName[0] != '\0') {\r
483         fprintf (stdout, "%s...\n", mUtilityName);\r
484       }\r
485       sprintf (Line, "%s", Cptr);\r
486       if (LineNumber != 0) {\r
487         sprintf (Line2, "(%u)", (unsigned) LineNumber);\r
488         strcat (Line, Line2);\r
489       }\r
490     } else {\r
491       if (mUtilityName[0] != '\0') {\r
492         sprintf (Line, "%s", mUtilityName);\r
493       }\r
494     }\r
495 \r
496     if (strcmp (Type, "ERROR") == 0) {\r
497       //\r
498       // Set status accordingly for ERROR information.\r
499       //\r
500       if (mStatus < STATUS_ERROR) {\r
501         mStatus = STATUS_ERROR;\r
502       }\r
503     }\r
504   }\r
505 \r
506   //\r
507   // Have to print an error code or Visual Studio won't find the\r
508   // message for you. It has to be decimal digits too.\r
509   //\r
510   if (MessageCode != 0) {\r
511     sprintf (Line2, ": %s %04u", Type, (unsigned) MessageCode);\r
512   } else {\r
513     sprintf (Line2, ": %s", Type);\r
514   }\r
515   strcat (Line, Line2);\r
516   fprintf (stdout, "%s", Line);\r
517   //\r
518   // If offending text was provided, then print it\r
519   //\r
520   if (Text != NULL) {\r
521     fprintf (stdout, ": %s", Text);\r
522   }\r
523   fprintf (stdout, "\n");\r
524 \r
525   //\r
526   // Print formatted message if provided\r
527   //\r
528   if (MsgFmt != NULL) {\r
529     vsprintf (Line2, MsgFmt, List);\r
530     fprintf (stdout, "  %s\n", Line2);\r
531   }\r
532 \r
533 }\r
534 \r
535 STATIC\r
536 VOID\r
537 PrintSimpleMessage (\r
538   CHAR8   *MsgFmt,\r
539   va_list List\r
540   )\r
541 /*++\r
542 Routine Description:\r
543   Print message into stdout.\r
544 \r
545 Arguments:\r
546   MsgFmt      - the format string for the message. Can contain formatting\r
547                 controls for use with varargs.\r
548   List        - the variable list.\r
549 \r
550 Returns:\r
551   None.\r
552 --*/\r
553 {\r
554   CHAR8       Line[MAX_LINE_LEN];\r
555   //\r
556   // Print formatted message if provided\r
557   //\r
558   if (MsgFmt != NULL) {\r
559     vsprintf (Line, MsgFmt, List);\r
560     fprintf (stdout, "%s\n", Line);\r
561   }\r
562 }\r
563 \r
564 VOID\r
565 ParserSetPosition (\r
566   CHAR8   *SourceFileName,\r
567   UINT32  LineNum\r
568   )\r
569 /*++\r
570 \r
571 Routine Description:\r
572   Set the position in a file being parsed. This can be used to\r
573   print error messages deeper down in a parser.\r
574 \r
575 Arguments:\r
576   SourceFileName - name of the source file being parsed\r
577   LineNum        - line number of the source file being parsed\r
578 \r
579 Returns:\r
580   NA\r
581 \r
582 --*/\r
583 {\r
584   mSourceFileName     = SourceFileName;\r
585   mSourceFileLineNum  = LineNum;\r
586 }\r
587 \r
588 VOID\r
589 SetUtilityName (\r
590   CHAR8   *UtilityName\r
591   )\r
592 /*++\r
593 \r
594 Routine Description:\r
595   All printed error/warning/debug messages follow the same format, and\r
596   typically will print a filename or utility name followed by the error\r
597   text. However if a filename is not passed to the print routines, then\r
598   they'll print the utility name if you call this function early in your\r
599   app to set the utility name.\r
600 \r
601 Arguments:\r
602   UtilityName  -  name of the utility, which will be printed with all\r
603                   error/warning/debug messags.\r
604 \r
605 Returns:\r
606   NA\r
607 \r
608 --*/\r
609 {\r
610   //\r
611   // Save the name of the utility in our local variable. Make sure its\r
612   // length does not exceed our buffer.\r
613   //\r
614   if (UtilityName != NULL) {\r
615     if (strlen (UtilityName) >= sizeof (mUtilityName)) {\r
616       Error (UtilityName, 0, 0, "application error", "utility name length exceeds internal buffer size");\r
617       strncpy (mUtilityName, UtilityName, sizeof (mUtilityName) - 1);\r
618       mUtilityName[sizeof (mUtilityName) - 1] = 0;\r
619       return ;\r
620     } else {\r
621       strcpy (mUtilityName, UtilityName);\r
622     }\r
623   } else {\r
624     Error (NULL, 0, 0, "application error", "SetUtilityName() called with NULL utility name");\r
625   }\r
626 }\r
627 \r
628 STATUS\r
629 GetUtilityStatus (\r
630   VOID\r
631   )\r
632 /*++\r
633 \r
634 Routine Description:\r
635   When you call Error() or Warning(), this module keeps track of it and\r
636   sets a local mStatus to STATUS_ERROR or STATUS_WARNING. When the utility\r
637   exits, it can call this function to get the status and use it as a return\r
638   value.\r
639 \r
640 Arguments:\r
641   None.\r
642 \r
643 Returns:\r
644   Worst-case status reported, as defined by which print function was called.\r
645 \r
646 --*/\r
647 {\r
648   return mStatus;\r
649 }\r
650 \r
651 VOID\r
652 SetPrintLevel (\r
653   UINT64  LogLevel\r
654   )\r
655 /*++\r
656 \r
657 Routine Description:\r
658   Set the printing message Level. This is used by the PrintMsg() function\r
659   to determine when/if a message should be printed.\r
660 \r
661 Arguments:\r
662   LogLevel  - 0~50 to specify the different level message.\r
663 \r
664 Returns:\r
665   NA\r
666 \r
667 --*/\r
668 {\r
669   mPrintLogLevel = LogLevel;\r
670 }\r
671 \r
672 VOID\r
673 VerboseMsg (\r
674   CHAR8   *MsgFmt,\r
675   ...\r
676   )\r
677 /*++\r
678 \r
679 Routine Description:\r
680   Print a verbose level message.\r
681 \r
682 Arguments:\r
683   MsgFmt      - the format string for the message. Can contain formatting\r
684                 controls for use with varargs.\r
685   List        - the variable list.\r
686 \r
687 Returns:\r
688   NA\r
689 \r
690 --*/\r
691 {\r
692   va_list List;\r
693   //\r
694   // If the debug level is less than current print level, then do nothing.\r
695   //\r
696   if (VERBOSE_LOG_LEVEL < mPrintLogLevel) {\r
697     return ;\r
698   }\r
699 \r
700   va_start (List, MsgFmt);\r
701   PrintSimpleMessage (MsgFmt, List);\r
702   va_end (List);\r
703 }\r
704 \r
705 VOID\r
706 NormalMsg (\r
707   CHAR8   *MsgFmt,\r
708   ...\r
709   )\r
710 /*++\r
711 \r
712 Routine Description:\r
713   Print a default level message.\r
714 \r
715 Arguments:\r
716   MsgFmt      - the format string for the message. Can contain formatting\r
717                 controls for use with varargs.\r
718   List        - the variable list.\r
719 \r
720 Returns:\r
721   NA\r
722 \r
723 --*/\r
724 {\r
725   va_list List;\r
726   //\r
727   // If the debug level is less than current print level, then do nothing.\r
728   //\r
729   if (INFO_LOG_LEVEL < mPrintLogLevel) {\r
730     return ;\r
731   }\r
732 \r
733   va_start (List, MsgFmt);\r
734   PrintSimpleMessage (MsgFmt, List);\r
735   va_end (List);\r
736 }\r
737 \r
738 VOID\r
739 KeyMsg (\r
740   CHAR8   *MsgFmt,\r
741   ...\r
742   )\r
743 /*++\r
744 \r
745 Routine Description:\r
746   Print a key level message.\r
747 \r
748 Arguments:\r
749   MsgFmt      - the format string for the message. Can contain formatting\r
750                 controls for use with varargs.\r
751   List        - the variable list.\r
752 \r
753 Returns:\r
754   NA\r
755 \r
756 --*/\r
757 {\r
758   va_list List;\r
759   //\r
760   // If the debug level is less than current print level, then do nothing.\r
761   //\r
762   if (KEY_LOG_LEVEL < mPrintLogLevel) {\r
763     return ;\r
764   }\r
765 \r
766   va_start (List, MsgFmt);\r
767   PrintSimpleMessage (MsgFmt, List);\r
768   va_end (List);\r
769 }\r
770 \r
771 VOID\r
772 SetPrintLimits (\r
773   UINT32  MaxErrors,\r
774   UINT32  MaxWarnings,\r
775   UINT32  MaxWarningsPlusErrors\r
776   )\r
777 /*++\r
778 \r
779 Routine Description:\r
780   Set the limits of how many errors, warnings, and errors+warnings\r
781   we will print.\r
782 \r
783 Arguments:\r
784   MaxErrors       - maximum number of error messages to print\r
785   MaxWarnings     - maximum number of warning messages to print\r
786   MaxWarningsPlusErrors\r
787                   - maximum number of errors+warnings to print\r
788 \r
789 Returns:\r
790   NA\r
791 \r
792 --*/\r
793 {\r
794   mMaxErrors              = MaxErrors;\r
795   mMaxWarnings            = MaxWarnings;\r
796   mMaxWarningsPlusErrors  = MaxWarningsPlusErrors;\r
797   mPrintLimitsSet         = 1;\r
798 }\r
799 \r
800 STATIC\r
801 VOID\r
802 PrintLimitExceeded (\r
803   VOID\r
804   )\r
805 {\r
806   STATIC INT8 mPrintLimitExceeded = 0;\r
807   //\r
808   // If we've already printed the message, do nothing. Otherwise\r
809   // temporarily increase our print limits so we can pass one\r
810   // more message through.\r
811   //\r
812   if (mPrintLimitExceeded == 0) {\r
813     mPrintLimitExceeded++;\r
814     mMaxErrors++;\r
815     mMaxWarnings++;\r
816     mMaxWarningsPlusErrors++;\r
817     Error (NULL, 0, 0, "error/warning print limit exceeded", NULL);\r
818     mMaxErrors--;\r
819     mMaxWarnings--;\r
820     mMaxWarningsPlusErrors--;\r
821   }\r
822 }\r
823 \r
824 #if 0\r
825 VOID\r
826 TestUtilityMessages (\r
827   VOID\r
828   )\r
829 {\r
830   CHAR8 *ArgStr = "ArgString";\r
831   int   ArgInt;\r
832 \r
833   ArgInt  = 0x12345678;\r
834   //\r
835   // Test without setting utility name\r
836   //\r
837   fprintf (stdout, "* Testing without setting utility name\n");\r
838   fprintf (stdout, "** Test debug message not printed\n");\r
839   DebugMsg (NULL, 0, 0x00000001, NULL, NULL);\r
840   fprintf (stdout, "** Test warning with two strings and two args\n");\r
841   Warning (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);\r
842   fprintf (stdout, "** Test error with two strings and two args\n");\r
843   Warning (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);\r
844   fprintf (stdout, "** Test parser warning with nothing\n");\r
845   ParserWarning (0, NULL, NULL);\r
846   fprintf (stdout, "** Test parser error with nothing\n");\r
847   ParserError (0, NULL, NULL);\r
848   //\r
849   // Test with utility name set now\r
850   //\r
851   fprintf (stdout, "** Testingin with utility name set\n");\r
852   SetUtilityName ("MyUtilityName");\r
853   //\r
854   // Test debug prints\r
855   //\r
856   SetDebugMsgMask (2);\r
857   fprintf (stdout, "** Test debug message with one string\n");\r
858   DebugMsg (NULL, 0, 0x00000002, "Text1", NULL);\r
859   fprintf (stdout, "** Test debug message with one string\n");\r
860   DebugMsg (NULL, 0, 0x00000002, NULL, "Text2");\r
861   fprintf (stdout, "** Test debug message with two strings\n");\r
862   DebugMsg (NULL, 0, 0x00000002, "Text1", "Text2");\r
863   fprintf (stdout, "** Test debug message with two strings and two args\n");\r
864   DebugMsg (NULL, 0, 0x00000002, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);\r
865   //\r
866   // Test warning prints\r
867   //\r
868   fprintf (stdout, "** Test warning with no strings\n");\r
869   Warning (NULL, 0, 1234, NULL, NULL);\r
870   fprintf (stdout, "** Test warning with one string\n");\r
871   Warning (NULL, 0, 1234, "Text1", NULL);\r
872   fprintf (stdout, "** Test warning with one string\n");\r
873   Warning (NULL, 0, 1234, NULL, "Text2");\r
874   fprintf (stdout, "** Test warning with two strings and two args\n");\r
875   Warning (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);\r
876   //\r
877   // Test error prints\r
878   //\r
879   fprintf (stdout, "** Test error with no strings\n");\r
880   Error (NULL, 0, 1234, NULL, NULL);\r
881   fprintf (stdout, "** Test error with one string\n");\r
882   Error (NULL, 0, 1234, "Text1", NULL);\r
883   fprintf (stdout, "** Test error with one string\n");\r
884   Error (NULL, 0, 1234, NULL, "Text2");\r
885   fprintf (stdout, "** Test error with two strings and two args\n");\r
886   Error (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);\r
887   //\r
888   // Test parser prints\r
889   //\r
890   fprintf (stdout, "** Test parser errors\n");\r
891   ParserSetPosition (__FILE__, __LINE__ + 1);\r
892   ParserError (1234, NULL, NULL);\r
893   ParserSetPosition (__FILE__, __LINE__ + 1);\r
894   ParserError (1234, "Text1", NULL);\r
895   ParserSetPosition (__FILE__, __LINE__ + 1);\r
896   ParserError (1234, NULL, "Text2");\r
897   ParserSetPosition (__FILE__, __LINE__ + 1);\r
898   ParserError (1234, "Text1", "Text2");\r
899   ParserSetPosition (__FILE__, __LINE__ + 1);\r
900   ParserError (1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);\r
901 \r
902   fprintf (stdout, "** Test parser warnings\n");\r
903   ParserSetPosition (__FILE__, __LINE__ + 1);\r
904   ParserWarning (4321, NULL, NULL);\r
905   ParserSetPosition (__FILE__, __LINE__ + 1);\r
906   ParserWarning (4321, "Text1", NULL);\r
907   ParserSetPosition (__FILE__, __LINE__ + 1);\r
908   ParserWarning (4321, NULL, "Text2");\r
909   ParserSetPosition (__FILE__, __LINE__ + 1);\r
910   ParserWarning (4321, "Text1", "Text2");\r
911   ParserSetPosition (__FILE__, __LINE__ + 1);\r
912   ParserWarning (4321, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt);\r
913 }\r
914 #endif\r